C语言多进程场景下wait()失效 父进程读取二进制文件结果为0问题排查
问题根因
1. 进程分支逻辑错位
fork()返回值大于0为父进程,等于0为子进程,你代码中的分支注释完全错误,将等待子进程、读取文件的逻辑放在了第二个子进程的执行分支中:
- 负责执行读文件逻辑的进程本身没有任何子进程,
wait(NULL)调用直接报错返回,没有等待两个计算子进程执行完成就提前读文件,自然读不到有效数据 - 真正的原始父进程没有任何等待逻辑,创建第一个子进程后直接退出,和你的设计预期完全不符。
2. 标准IO缓冲区隔离
fork()会复制父进程的地址空间,每个进程持有的FILE*对应独立的用户态缓冲区:
- 子进程调用
fwrite()写入的数据首先存放在自身的用户态缓冲区,默认不会立刻写入磁盘 - 即使子进程退出时会自动刷写缓冲区,也晚于错位逻辑中提前执行的读操作
- 多个进程持有同一个文件句柄的拷贝,各自维护独立的文件偏移,还可能出现写入数据覆盖的问题。
3. 文件打开模式非法
读文件时使用的"rw"不是C标准fopen支持的合法模式,读取二进制文件需使用"rb"模式,非法模式会导致读取异常。
修复建议
- 调整分支逻辑,将等待子进程、读取文件的逻辑移到原始父进程分支,父进程调用两次
wait(NULL)等待两个子进程全部退出 - 子进程写入完成后主动调用
fflush(ptrW)刷写缓冲区,确保数据写入磁盘,也可以直接在子进程中关闭打开的文件句柄 - 将读文件的打开模式修改为
"rb" - 建议两个子进程分别打开文件写入,或者用更稳妥的进程间通信方式传递计算结果,避免多进程写同一个文件出现偏移异常
修复后的参考代码:
#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
相关产品推荐
相关产品推荐

