基于Linux C的信号量实现生产者消费者问题及代码咨询
Troubleshooting & Guidance for Your Linux C Producer-Consumer Implementation
Hey there, let's dig into your producer-consumer implementation using semaphores and shared memory in Linux C. I immediately spotted a critical bug in your code snippet that's going to break things right away, plus a few other key points to address:
Critical Bug: Shared Memory ID Overwrite
You're overwriting the valid shared memory IDs right after retrieving them:
shmid_get = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT|0600); shmid_set = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT|0600); **shmid_get = 0; **shmid_set = 0; // This is the bug!
Setting shmid_get and shmid_set to 0 discards the IDs returned by shmget(), which means you'll never be able to attach to those shared memory segments later with shmat(). Delete those two lines immediately.
Fixed & Improved Code Snippet
Here's a corrected version of your initial code with proper error handling, shared memory attachment, and clearer naming:
#include <stdio.h> #include <sys/ipc.h> #include <sys/shm.h> #include <semaphore.h> #include <stdlib.h> #include <unistd.h> sem_t mutex; sem_t empty; sem_t full; int main() { int shmid_buffer; int shmid_read_idx; int shmid_write_idx; int *buffer = NULL; int *read_idx = NULL; int *write_idx = NULL; // Create shared memory for the 20-int buffer shmid_buffer = shmget(IPC_PRIVATE, 20 * sizeof(int), IPC_CREAT | 0600); if (shmid_buffer == -1) { perror("Failed to create buffer shared memory"); exit(EXIT_FAILURE); } // Create shared memory for read index shmid_read_idx = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600); if (shmid_read_idx == -1) { perror("Failed to create read index shared memory"); exit(EXIT_FAILURE); } // Create shared memory for write index shmid_write_idx = shmget(IPC_PRIVATE, sizeof(int), IPC_CREAT | 0600); if (shmid_write_idx == -1) { perror("Failed to create write index shared memory"); exit(EXIT_FAILURE); } // Initialize semaphores (pshared=1 for inter-process use) if (sem_init(&mutex, 1, 1) == -1) { perror("Failed to initialize mutex semaphore"); exit(EXIT_FAILURE); } if (sem_init(&full, 1, 0) == -1) { perror("Failed to initialize full semaphore"); exit(EXIT_FAILURE); } if (sem_init(&empty, 1, 20) == -1) { perror("Failed to initialize empty semaphore"); exit(EXIT_FAILURE); } // Attach shared memory segments to process address space buffer = (int*)shmat(shmid_buffer, NULL, 0); if (buffer == (void*)-1) { perror("Failed to attach buffer shared memory"); exit(EXIT_FAILURE); } read_idx = (int*)shmat(shmid_read_idx, NULL, 0); if (read_idx == (void*)-1) { perror("Failed to attach read index shared memory"); exit(EXIT_FAILURE); } *read_idx = 0; // Initialize read position to start of buffer write_idx = (int*)shmat(shmid_write_idx, NULL, 0); if (write_idx == (void*)-1) { perror("Failed to attach write index shared memory"); exit(EXIT_FAILURE); } *write_idx = 0; // Initialize write position to start of buffer // --- Add your producer/consumer fork/thread logic here --- // Example producer action (simplified): // sem_wait(&empty); // sem_wait(&mutex); // buffer[*write_idx] = some_value; // *write_idx = (*write_idx + 1) % 20; // Wrap around buffer // sem_post(&mutex); // sem_post(&full); // Example consumer action (simplified): // sem_wait(&full); // sem_wait(&mutex); // int value = buffer[*read_idx]; // *read_idx = (*read_idx + 1) % 20; // Wrap around buffer // sem_post(&mutex); // sem_post(&empty); // Cleanup (use atexit() to ensure this runs even on unexpected exit) shmdt(buffer); shmdt(read_idx); shmdt(write_idx); shmctl(shmid_buffer, IPC_RMID, NULL); shmctl(shmid_read_idx, IPC_RMID, NULL); shmctl(shmid_write_idx, IPC_RMID, NULL); sem_destroy(&mutex); sem_destroy(&full); sem_destroy(&empty); return 0; }
Key Additional Guidance
- Error Handling is Non-Negotiable: Every IPC system call (
shmget,shmat,sem_init,sem_wait,sem_post) can fail. Always check return values and useperror()to get meaningful error messages—this will save you hours of debugging. - Semaphore Order Prevents Deadlocks: For producers, always acquire
emptybeforemutex; for consumers, acquirefullbeforemutex. Reversing this order can lead to permanent deadlocks. - Cleanup Resources Properly: Shared memory segments and semaphores don't auto-clean when your program exits. Use
shmctl(IPC_RMID)to delete shared memory andsem_destroy()to clean up semaphores. Registering cleanup functions withatexit()ensures this happens even if your program crashes. - Compile with
-lpthread: Semaphore functions require linking against the pthread library. Compile your code with:gcc your_program.c -o your_program -lpthread
内容的提问来源于stack exchange,提问作者peter
相关产品推荐
相关产品推荐

