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

如何正确从共享内存获取信号量?进程因信号量阻塞无报错

进程同步信号量阻塞问题

我有一个库会向共享内存(shared memory)中的数组写入数据,现在需要实现进程同步,因为会有多个进程访问并向该数组添加元素。我正在学习信号量(semaphore),但不理解为何进程会陷入阻塞且无任何报错。注释掉getSemaphoreWrite()和releaseSemaphoreWrite()相关代码行后,进程就能正常运行,和未使用信号量时表现一致。

库代码

void getSemaphoreWrite(){
    int semID = semget(KEY_MB_WRITE, 0,0600);
    struct sembuf sops;
    sops.sem_num = 0;
    sops.sem_op = -1;
    semop(semID,&sops,1);
}
void releaseSemaphoreWrite(){
    int semID = semget(KEY_MB_WRITE, 0,0600);
    struct sembuf sops;
    sops.sem_num = 0;
    sops.sem_op = 1;
    semop(semID,&sops,1);
} 
int addBlock(struct Block block){
    if(sizeMaster >= MAX_MASTER-1) return -1;
    getSemaphoreWrite();
    block.id = sizeMaster +1 ;
    MasterBook[sizeMaster] = block;
    ++sizeMaster;
    printf("After add a block, size: %d",sizeMaster);
    releaseSemaphoreWrite();
    return 0;
}

结构体定义

struct Transaction {
    int empty;
    char timestamp[30];
    int sender; /* 发送方进程ID */
    int receiver;
    int reward;
    int money;
};

struct Block
{
    int id;
    struct Transaction tr1;
    struct Transaction tr2;
    struct Transaction reward;
};

主进程代码

int semID = semget(KEY_MB_WRITE, 1, IPC_CREAT | 0600);
if(semID == -1){
    perror("Error in sem: ");
    exit(EXIT_FAILURE);
}
semctl(semID, 0, SETVAL, 0);

问题原因与解决方法

核心问题

你把信号量初始值设成了0,而getSemaphoreWrite()里调用semop时用了sem_op = -1——这会尝试将信号量值减1,但初始值是0,减1后就会变成负数,触发信号量阻塞机制,进程会一直等待信号量值回到非负状态,自然就卡着不动了。

修复步骤

  1. 修正信号量初始值:主进程里把semctl的第三个参数改成1,这样初始信号量值是1,对应互斥锁的场景(同一时间只有一个进程能获取锁):
    semctl(semID, 0, SETVAL, 1);
    
  2. 添加错误检查:你的信号量操作函数里没做错误处理,一旦semget或semop调用失败(比如KEY不正确、权限不够),会导致静默失败,难排查。给getSemaphoreWrite()和releaseSemaphoreWrite()加上错误判断:
    void getSemaphoreWrite(){
        int semID = semget(KEY_MB_WRITE, 0,0600);
        if(semID == -1) {
            perror("semget failed in getSemaphoreWrite");
            exit(EXIT_FAILURE);
        }
        struct sembuf sops;
        sops.sem_num = 0;
        sops.sem_op = -1;
        if(semop(semID,&sops,1) == -1) {
            perror("semop failed in getSemaphoreWrite");
            exit(EXIT_FAILURE);
        }
    }
    
    void releaseSemaphoreWrite(){
        int semID = semget(KEY_MB_WRITE, 0,0600);
        if(semID == -1) {
            perror("semget failed in releaseSemaphoreWrite");
            exit(EXIT_FAILURE);
        }
        struct sembuf sops;
        sops.sem_num = 0;
        sops.sem_op = 1;
        if(semop(semID,&sops,1) == -1) {
            perror("semop failed in releaseSemaphoreWrite");
            exit(EXIT_FAILURE);
        }
    }
    
  3. 确认共享内存变量同步:sizeMaster是共享内存里的变量吗?如果不是,多个进程会各自维护一份副本,导致同步失效。要确保sizeMaster和MasterBook都存放在共享内存区域。

内容的提问来源于stack exchange,提问作者Matteo Pagliarello

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:36:23