如何正确从共享内存获取信号量?进程因信号量阻塞无报错
进程同步信号量阻塞问题
我有一个库会向共享内存(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后就会变成负数,触发信号量阻塞机制,进程会一直等待信号量值回到非负状态,自然就卡着不动了。
修复步骤
- 修正信号量初始值:主进程里把
semctl的第三个参数改成1,这样初始信号量值是1,对应互斥锁的场景(同一时间只有一个进程能获取锁):semctl(semID, 0, SETVAL, 1); - 添加错误检查:你的信号量操作函数里没做错误处理,一旦
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); } } - 确认共享内存变量同步:
sizeMaster是共享内存里的变量吗?如果不是,多个进程会各自维护一份副本,导致同步失效。要确保sizeMaster和MasterBook都存放在共享内存区域。
内容的提问来源于stack exchange,提问作者Matteo Pagliarello
相关产品推荐
相关产品推荐

