管道进程无stdout输出问题排查(cat与grep管道示例)
问题排查与修复
1. 第一个子进程参数数组未以NULL终止
execvp要求传入的参数数组必须以NULL结尾,否则会读取超出数组范围的内存,导致程序行为异常(比如cat命令无法正确执行,没有输出到管道)。
你的代码中,为第一个子进程(执行cat)构建参数数组时,仅复制了pipe_loc个元素,未添加终止的NULL:
for(int i = 0; i < pipe_loc; i++){ //args for output child arr_out[i] = args[i]; } // 缺少终止NULL,导致execvp行为异常
修复:在循环结束后添加arr_out[pipe_loc] = NULL;,确保参数数组符合execvp的要求。
2. waitpid 循环条件逻辑错误
当前的等待循环条件逻辑完全错误:
while(!WIFEXITED(status_1) && WIFSIGNALED(status_1) && !WIFEXITED(status_2) && WIFSIGNALED(status_2));
该条件要求“两个子进程都未正常退出且都被信号终止”才继续等待,这几乎永远不成立,会导致父进程提前结束,可能在子进程还未完成管道数据传输时就退出,最终导致grep无输出。
修复:修改为只要任意一个子进程还未正常退出或被信号终止,就持续等待:
do { wpid_1 = waitpid(child_out, &status_1, WUNTRACED); wpid_2 = waitpid(child_in, &status_2, WUNTRACED); } while ( (!WIFEXITED(status_1) && !WIFSIGNALED(status_1)) || (!WIFEXITED(status_2) && !WIFSIGNALED(status_2)) );
3. 冗余代码优化(非功能性问题)
第二个子进程中的break语句完全冗余,因为循环范围已经限定了i的取值,j最终会自然到达目标值,可删除该语句简化代码:
int j = 0; for(int i = pipe_loc+1; i < argc ; i++){ arr_in[j++] = args[i]; } arr_in[j] = NULL;
修复后验证
修复以上问题后,cat crash.c会正确将内容写入管道,grep 'main'从管道读取输入后,其stdout并未被修改(代码仅重定向了它的stdin),匹配结果会正常打印到终端。
内容的提问来源于stack exchange,提问作者Gowtham_M
相关产品推荐
相关产品推荐

