我有以下程序,只是为了测试我是否理解分叉和共享内存。 总而言之,它会创建共享内存,分叉,分叉,分叉,并在每个分叉中写入数据并退出。
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main() {
key_t key = ftok(".", 'x');
int shmid = shmget(key, sizeof(int)*4, IPC_CREAT | 0666);
if (shmid < 0) {
perror("shmget\n");
return 1;
}
int *arr = shmat(shmid, NULL, 0);
pid_t c1 = fork();
if (c1==0) {
pid_t c2 = fork();
if (c2==0) {
pid_t c3 = fork();
if (c3==0) {
arr[0] = 10;
} else {
arr[1] = 11;
}
exit(0);
} else {
arr[2] = 12;
}
exit(0);
} else {
arr[3] = 13;
wait(NULL);
wait(NULL);
wait(NULL);
for (int i=0; i<4; i++) printf("%d ", arr[i]);
printf("\n");
}
exit(0);
}
这会打印
0 11 12 13
,表明由于某种原因,值 10
从未分配给 arr[0]
。
我预计每个进程都会对
exit(0)
进行一些调用。 特别是第三个分叉之后的那个,我认为应该达到与第二个分叉所达到的相同的对 exit(0)
的调用。
但是,当我在第三个 fork 的块内添加对 exit 的显式调用时(即在
c3==0
之后),它就会按预期执行。
当我写这篇文章时,我突然猜测为什么会发生这种情况:是不是因为第二个子节点在第三个子节点之前到达退出,并且因为它退出,所以从第四个子节点到父节点的链接被破坏了?
您当前尝试对原始父进程中的三个进程进行
wait
,但它只有一个子进程,因此只有第一次等待成功。在打印结果之前,无法保证其他进程已准备好写入。
为了确保孩子们都完成,每个家长都可以等待自己的孩子。
示例:
pid_t c1 = fork();
if (c1==0) { // child
pid_t c2 = fork();
if (c2==0) { // child
pid_t c3 = fork();
if (c3==0) { // child
arr[0] = 10;
} else {
arr[1] = 11;
}
waitpid(c3, NULL, 0); // waiting for child
exit(0);
} else {
arr[2] = 12;
}
waitpid(c2, NULL, 0); // waiting for child
exit(0);
} else {
arr[3] = 13;
waitpid(c1, NULL, 0); // waiting for child
for (int i=0; i<4; i++) printf("%d ", arr[i]);
printf("\n");
}