You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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 use perror() to get meaningful error messages—this will save you hours of debugging.
  • Semaphore Order Prevents Deadlocks: For producers, always acquire empty before mutex; for consumers, acquire full before mutex. 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 and sem_destroy() to clean up semaphores. Registering cleanup functions with atexit() 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 10:00:38