fork进程未执行exit(0)致共享内存赋值异常问题排查
问题分析与解决
你的核心问题是没给所有子进程添加显式的exit(0),导致子进程继续执行后续的fork()调用,彻底打乱了原本的写入逻辑,和你猜测的“第二个子进程退出导致第四个进程与父进程链接断裂”无关。
三次fork()的执行逻辑
每次fork()会创建一个新进程,父进程和子进程都会从fork()的下一行代码继续执行。如果子进程不调用exit(),它会完全复刻父进程的后续行为——包括执行剩下的fork():
- 第一次
fork()后:父进程+子进程A(共2个) - 子进程A若没
exit(),会执行第二次fork()创建子进程A1;同时父进程也执行第二次fork()创建子进程B(共4个) - 这4个进程若都没
exit(),都会执行第三次fork(),最终生成8个进程
为什么arr[0]没被赋值为10?
假设你的代码逻辑是“每个fork()的子进程对应写入一个数组元素”,但没加exit()的子进程会继续执行所有后续代码:
比如第一个fork()产生的子进程A,写完arr[0]=10后不退出,会继续执行第二次fork(),成为新的父进程;接着执行第三次fork(),又成为父进程。这会导致:
- 进程数量远超预期,多个进程可能重复执行写入逻辑,甚至覆盖已有值
- 父进程的
wait()只能等待自己的直接子进程,而子进程A创建的后代进程,父进程无法感知,可能在所有写入操作完成前就输出结果 - 子进程A本身会执行后续的父进程逻辑(比如
wait()、printf()),干扰共享内存的最终状态
正确的解决方案
所有子进程在完成写入操作后必须立即调用exit(0),阻止它执行后续代码:
#include <stdio.h> #include <sys/shm.h> #include <sys/wait.h> #include <stdlib.h> int main() { int shmid = shmget(IPC_PRIVATE, 4 * sizeof(int), IPC_CREAT | 0666); int *arr = shmat(shmid, NULL, 0); // 初始化共享内存为0 arr[0] = arr[1] = arr[2] = arr[3] = 0; pid_t p1 = fork(); if (p1 == 0) { arr[0] = 10; exit(0); // 写完立即退出 } pid_t p2 = fork(); if (p2 == 0) { arr[1] = 11; exit(0); // 写完立即退出 } pid_t p3 = fork(); if (p3 == 0) { arr[2] = 12; arr[3] = 13; exit(0); // 写完立即退出 } // 等待所有直接子进程退出 wait(NULL); wait(NULL); wait(NULL); printf("%d %d %d %d\n", arr[0], arr[1], arr[2], arr[3]); // 清理共享内存 shmdt(arr); shmctl(shmid, IPC_RMID, NULL); return 0; }
这样三次fork()只会创建3个目标子进程,每个子进程仅执行自己的写入操作后退出,父进程等待所有子进程完成后再输出,就能得到预期的10 11 12 13。
关于你的猜测补充
进程的父子关系不会因其他进程退出而断裂——除非父进程退出,子进程会被系统进程(如init/systemd)收养,但这完全不影响共享内存的访问(只要共享内存未被销毁,所有挂载它的进程都能正常读写)。你的问题本质是子进程未及时退出导致的逻辑混乱,和父子进程链接无关。
内容的提问来源于stack exchange,提问作者Addem
相关产品推荐
相关产品推荐

