使用fork()和pipe()实现1-100有序输出的程序调试问题
问题分析与修复方案
我一眼就看出你的代码里几个关键问题,直接导致进程卡在printProc函数里,咱们一步步拆解:
核心问题1:管道读写端完全搞反了
管道创建后,fd[0]是读端,fd[1]是写端,但你的代码完全搞反了读写方向:
- 初始同步时你写了
write(fd[0], &start, sizeof(start));,这是往读端写数据,完全无效 - 在
printProc里又用read(fd[1], &proc, sizeof(proc));,从写端读数据,根本读不到任何内容,进程自然会一直阻塞在这里
核心问题2:初始同步逻辑错误
你想通过管道传递proc值来控制进程交替输出,但初始写入的start=0没有正确进入管道,子进程(负责输出奇数,procNumber=0)根本读不到初始的控制信号,没法启动输出流程。
其他小问题
- 多个进程同时用
a+模式打开文件,虽然POSIX下追加写入是原子操作,但缺少缓存刷新,可能导致内容写入延迟 - 没有关闭管道的未使用端,可能导致进程结束时无法正确释放资源,甚至意外阻塞
修复后的完整代码
#include <stdio.h> #include <unistd.h> #include <sys/types.h> #include <stdlib.h> int fd[2]; int printProc(int startNumber, int procNumber); int main() { pid_t childpid; // 增加管道创建的错误检查 if (pipe(fd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } int start = 0; // 往管道写端(fd[1])写入初始控制值 write(fd[1], &start, sizeof(start)); if ((childpid = fork()) == -1) { perror("fork"); exit(EXIT_FAILURE); } if (childpid == 0) { printf("run child (odd numbers)\n"); // 子进程不需要写管道,关闭写端 close(fd[1]); printProc(1, 0); close(fd[0]); } else { printf("run parent (even numbers)\n"); // 父进程不需要读管道,关闭读端 close(fd[0]); printProc(2, 1); close(fd[1]); } return 0; } int printProc(int startNumber, int procNumber) { FILE *f = fopen("output.txt", "a"); if (!f) { perror("fopen"); return -1; } int num = startNumber; int proc; while (num <= 100) { // 从管道读端(fd[0])读取控制值 read(fd[0], &proc, sizeof(proc)); if (proc == procNumber) { fprintf(f, "%d ", num); fflush(f); // 立即刷新缓存,确保内容实时写入文件 printf("printed %d\n", num); // 控制台输出便于调试 num += 2; // 切换控制进程,写入管道写端(fd[1]) proc = (proc + 1) % 2; write(fd[1], &proc, sizeof(proc)); } } fclose(f); return 0; }
修复细节说明
- 修正管道读写端:所有
write操作使用fd[1](写端),read操作使用fd[0](读端),符合管道的标准用法 - 关闭未使用的管道端:子进程关闭写端、父进程关闭读端,避免进程结束时因管道未完全关闭导致的阻塞
- 文件操作优化:用
a模式代替a+(仅需追加写入),每次写入后调用fflush确保内容立即落盘,避免多进程缓存导致的顺序混乱 - 增强错误处理:添加了
pipe和fopen的错误检查,让程序更健壮
现在运行这个程序,output.txt里会按顺序输出1到100的所有数字,两个进程会交替执行,不会再卡住啦!
内容的提问来源于stack exchange,提问作者Claus Stolz
相关产品推荐
相关产品推荐

