我在 Unix C 中使用共享内存、信号量和分叉时遇到问题。我的信号量不是 posix。我创建了一个指向共享内存 2*sizeof(float) 的指针。我用 semctl 将信号量的值初始化为 2。我在 for 循环(i<2)中做了一个 fork()。在子进程中(如果 fork() == 0),每个子进程对信号量(-1)执行 ap 操作,写入共享内存然后执行 av 操作(+1)然后退出。父进程对信号量执行 ap 操作(-2),读取整个共享内存段(使用 for 循环)并执行 av 操作(+2)。他在退出之前等待子进程以避免僵尸。我在输出中遇到的问题是我得到:
Parent reading 0
Parent reading 1
Parent reading 0
Parent reading 1
Child writing 0
Child writing 1
当我应该得到的是:
Child writing 0
Child writing 1
Parent reading 0
Parent reading 1
我已经尝试将我的信号量初始化为 1 而不是 2,但这只会停止程序,因为信号量永远不会有值 2,因此父进程永远不会读取。
如果我对信号量的理解是正确的,那么我将它初始化为 2 的事实意味着即使没有孩子写任何东西,父进程也可以直接读取。我该如何解决这个问题?
编辑:我在请求后添加了我的代码的简化版本,我删除了错误检查,并等待孩子减少长度。
/** OPEN MEMORY **/
int shmid1 = shmget(1990, (size), IPC_CREAT | 0666 );
float * shmPt = (float*)shmat(shmid1, NULL, 0);
/** CREATE INITIALIZE SEMAPHORE **/
semun1.val = 2;
int semid = semget(1991, 1, 0666 | IPC_CREAT)
semctl(semid, 0, SETVAL, semun1 )
/** CREATE PROCESSES **/
for ( ii = 0; ii < 2; ++ii) {
if ((p = fork()) == 0) {
int semid = semget(1991, 1, 0666);
struct sembuf p_buf;
p_buf.sem_num = 0;p_buf.sem_op = -1;p_buf.sem_flg = SEM_UNDO;
/** LOCK **/
semop(semid, &p_buf,1);
/** WRITE **/
shmPt[ii] = RandomFloat;
v_buf.sem_num = 0;v_buf.sem_op = 1;v_buf.sem_flg = SEM_UNDO;
/** UNLOCK **/
semop(semid, &v_buf,1)
exit(0);
}
else {
int semid = semget(1991, 1, 0666);
struct sembuf p_buf;
p_buf.sem_num = 0;p_buf.sem_op = -2;p_buf.sem_flg = SEM_UNDO;
/** LOCK **/
semop(semid, &p_buf,1);
/** READ **/
for(int j =0;j<2;j++) tabFloat[j] = shmPt[j];
v_buf.sem_num = 0;v_buf.sem_op = 2;v_buf.sem_flg = SEM_UNDO;
/** UNLOCK **/
semop(semid, &v_buf,1)
}
}
编辑:我的最终目标是让 24 个孩子一个接一个地写入相同大小的共享内存段,并且只有当它已满时,父母才能读取所有内容并处理信息。最重要的是,所有这些都需要在一个 while 循环中进行(想象一下 24 辆汽车在每次完成一圈时不断生成随机时间,直到第一辆汽车完成 50 圈)