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

管道实现异常排查:为何ls |grep "main-pipe"|wc陷入无限循环?

问题排查与修复

核心问题:父进程没及时关闭管道的闲置端

你的代码里,父进程创建管道后,没及时关掉不用的管道描述符,导致后续进程没法检测到管道的EOF,直接卡成无限循环:

  1. ls子进程结束后,父进程还攥着pipe1的**写端(pipe1[1])**没关。这时候grep从pipe1读数据,虽然ls已经关了自己的写端,但父进程的写端还开着,grep会觉得可能还有数据进来,就一直堵在读取操作上不肯退出。父进程的wait(0)就一直等grep结束,俩进程互相耗着,就无限循环了。
  2. 同理,处理wc之前,父进程也得把没用的管道描述符都关干净。

其他坑点

  • execl("wc", "wc")没用到execlp,也没写wc的完整路径(比如/usr/bin/wc),系统可能找不到这个命令,直接执行失败。改成execlp("wc", "wc", (char*)NULL)就行,和grep的调用方式保持一致。

修复后的代码

#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <assert.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>

int main(int argc, char* argv[]) {
  if (argc > 1) {
    printf("Please don't provide additional arguments.\n");
    exit(1);
  }

  int pipe1[2];
  pipe(pipe1);

  int pid = fork();
  if (pid == 0) {
    // 重定向标准输出到pipe1写端
    close(1);
    dup(pipe1[1]);
    close(pipe1[1]);
    close(pipe1[0]);
    execlp("ls", "ls", (char*)NULL); // 补全NULL参数,符合调用规范
    perror("execlp ls failed");
    exit(1);
  }
  // 父进程关掉pipe1写端,反正不用写了
  close(pipe1[1]);
  wait(0);

  int pipe2[2];
  pipe(pipe2);

  pid = fork();
  if (pid == 0) {
    close(0);
    dup(pipe1[0]);
    close(pipe1[0]);

    close(1);
    dup(pipe2[1]);
    close(pipe2[1]);
    close(pipe2[0]);
    execlp("grep", "grep", "main-pipe", (char *)NULL);
    perror("execlp grep failed");
    exit(1);
  }
  // 父进程关掉pipe1读端和pipe2写端,闲置的都清掉
  close(pipe1[0]);
  close(pipe2[1]);
  wait(0);

  close(0);
  dup(pipe2[0]);
  close(pipe2[0]);

  execlp("wc", "wc", (char*)NULL);
  perror("execlp wc failed");
  exit(1);
}

关键修复说明

  • ls启动后,父进程立刻关pipe1[1],这样ls结束关了自己的写端后,pipe1所有写端都关闭了,grep读到EOF就会正常退出,不会一直等。
  • grep启动后,父进程关pipe1[0]和pipe2[1],避免这些闲置描述符搞事情。
  • 把execl改成execlp并补(char*)NULL,保证命令能找到,加perror方便出问题时查原因。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:07:04