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

C语言多进程场景下wait()失效 父进程读取二进制文件结果为0问题排查

问题根因

1. 进程分支逻辑错位

fork()返回值大于0为父进程,等于0为子进程,你代码中的分支注释完全错误,将等待子进程、读取文件的逻辑放在了第二个子进程的执行分支中:

  • 负责执行读文件逻辑的进程本身没有任何子进程,wait(NULL)调用直接报错返回,没有等待两个计算子进程执行完成就提前读文件,自然读不到有效数据
  • 真正的原始父进程没有任何等待逻辑,创建第一个子进程后直接退出,和你的设计预期完全不符。

2. 标准IO缓冲区隔离

fork()会复制父进程的地址空间,每个进程持有的FILE*对应独立的用户态缓冲区:

  • 子进程调用fwrite()写入的数据首先存放在自身的用户态缓冲区,默认不会立刻写入磁盘
  • 即使子进程退出时会自动刷写缓冲区,也晚于错位逻辑中提前执行的读操作
  • 多个进程持有同一个文件句柄的拷贝,各自维护独立的文件偏移,还可能出现写入数据覆盖的问题。

3. 文件打开模式非法

读文件时使用的"rw"不是C标准fopen支持的合法模式,读取二进制文件需使用"rb"模式,非法模式会导致读取异常。

修复建议
  1. 调整分支逻辑,将等待子进程、读取文件的逻辑移到原始父进程分支,父进程调用两次wait(NULL)等待两个子进程全部退出
  2. 子进程写入完成后主动调用fflush(ptrW)刷写缓冲区,确保数据写入磁盘,也可以直接在子进程中关闭打开的文件句柄
  3. 将读文件的打开模式修改为"rb"
  4. 建议两个子进程分别打开文件写入,或者用更稳妥的进程间通信方式传递计算结果,避免多进程写同一个文件出现偏移异常

修复后的参考代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#include <math.h>

double sumaTipo(int size, int inicio, int incremento) {
    double suma = 0;
    for (double i = inicio; i < size; i += incremento) {
        suma += tan(sqrt(i));
    }
    return suma;
}

double sumaImpares(int size) {
    return sumaTipo(size, 1, 2);
}

double sumaPares(int size) {
    return sumaTipo(size, 0, 2);
}

int main () {
    FILE *ptrW;
    int par1, par2;
    const int SIZE = 50000000;

    if ((ptrW = fopen("fichero.bin", "wb")) == NULL) {
        printf("Error en fopen\n");
        exit(0);
    }

    if ((par1 = fork()) == -1) {
        printf("Error en fork\n");
        exit(0);
    }

    if (par1 == 0) {
        // 第一个子进程:计算奇数和
        double suma = sumaImpares(SIZE);
        fwrite(&suma, sizeof(double), 1, ptrW);
        fflush(ptrW);
        printf("Hijo 1 acabado: %lf\n", suma);
        exit(EXIT_SUCCESS);
    } 

    // 父进程继续创建第二个子进程
    if ((par2 = fork()) == -1) {
        printf("Error en el fork\n");
        exit(0);
    }

    if (par2 == 0) {
        // 第二个子进程:计算偶数和
        double suma = sumaPares(SIZE);
        fwrite(&suma, sizeof(double), 1, ptrW);
        fflush(ptrW);
        printf("Hijo 2 acabado: %lf\n", suma);
        exit(EXIT_SUCCESS);
    }

    // 父进程逻辑:等待两个子进程退出后读文件
    wait(NULL);
    wait(NULL);
    fclose(ptrW);
    printf("Hijos acabados\n");
    FILE *ptrR;
    if ((ptrR = fopen("fichero.bin", "rb")) == NULL) {
        printf("Error en fopen\n");
        exit(0);
    }
    double result[2];
    fread(result, sizeof(double), 2, ptrR);
    printf("Resultado: %lf, %lf\n", result[0], result[1]);
    fclose(ptrR);
    return 0;
}

内容的提问来源于stack exchange,提问作者Landor3000

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:36:06