You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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(),又成为父进程。这会导致:

  1. 进程数量远超预期,多个进程可能重复执行写入逻辑,甚至覆盖已有值
  2. 父进程的wait()只能等待自己的直接子进程,而子进程A创建的后代进程,父进程无法感知,可能在所有写入操作完成前就输出结果
  3. 子进程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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:50:58