调用fork创建子进程后信号量无法在进程间共享值的问题
问题根因
你遇到的信号量父子进程值不一致问题,核心原因是你定义的sem_t semA存储在进程私有的全局内存区域:虽然sem_init的第二个参数pshared设为了1(代表支持进程间共享),但信号量本身没有放在跨进程共享的内存空间中。
fork()后父子进程的地址空间采用写时复制(COW)机制,父进程调用sem_wait修改信号量时,系统会为父进程复制一份新的信号量副本,子进程访问的仍然是原来的信号量副本,所以读到的值还是1。- 对于
sem_init初始化的匿名信号量,要实现进程间共享,必须将信号量对象存储在所有参与通信的进程都能访问的共享内存区域,这是强制要求。
修正后的代码示例
你可以用mmap创建匿名共享内存存储信号量,修正后的代码如下:
#include <stdlib.h> #include <unistd.h> #include <sys/wait.h> #include <sys/mman.h> #include <semaphore.h> #include <stdio.h> int *A; sem_t *semA; int main() { // 创建匿名共享映射,父子进程共享该区域 void *shm = mmap(NULL, sizeof(int) + sizeof(sem_t), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (shm == MAP_FAILED) { perror("mmap failed"); exit(1); } semA = (sem_t *)shm; A = (int *)(shm + sizeof(sem_t)); *A = 0; // 初始化共享信号量,pshared设为1 sem_init(semA, 1, 1); if(fork() == 0) { sleep(3); sem_getvalue(semA, A); printf("SemA Value child: %d\n", *A); exit(0); } else{ sem_wait(semA); sem_getvalue(semA, A); printf("SemA Value parent : %d\n", *A); } wait(NULL); sem_destroy(semA); munmap(shm, sizeof(int) + sizeof(sem_t)); return 0; }
额外说明
- 如果你不想手动管理共享内存,也可以选择命名信号量(用
sem_open创建,通过路径名标识,内核持久化),就不需要显式创建共享内存。 - 信号量的
pshared参数只是告诉内核这个信号量会被多进程共享,但前提是信号量本身的内存区域是多进程可见的,否则这个参数没有实际意义。
内容的提问来源于stack exchange,提问作者MADLOUF
相关产品推荐
相关产品推荐

