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

execlp调用异常:父子进程管道通信程序运行冻结排查

解决管道+more命令导致程序冻结的问题

嘿,我之前也碰到过一模一样的管道阻塞问题!看你贴的代码开头,结合你说的程序冻结情况,大概率是管道的文件描述符没有正确关闭,或者子进程的标准输入重定向没做对——毕竟more命令会一直等待输入,直到收到EOF才会退出,要是管道的写端没关,它就会一直卡着等数据。

常见的几个坑(也是我当初踩过的):

  • 父进程写完数据后没有关闭管道的写端:more会一直监听stdin,只要写端还被持有,就认为还有数据要传,不会退出。
  • 子进程没有把管道读端重定向到标准输入:more默认从stdin读,你得手动把管道的读端替换成stdin。
  • 父进程没有等待子进程执行完毕:可能导致子进程变成僵尸,或者管道状态异常。

修正后的完整代码示例

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

int main(void) {
    int fd[2];
    pid_t pid;

    // 创建管道
    if (pipe(fd) == -1) {
        perror("Error creating pipe");
        exit(EXIT_FAILURE);
    }

    // 创建子进程
    pid = fork();
    if (pid == -1) {
        perror("Error forking process");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) {
        // 子进程逻辑:调用more命令
        // 1. 关闭不需要的写端(子进程只需要读数据)
        close(fd[1]);

        // 2. 将管道读端重定向到标准输入(stdin)
        if (dup2(fd[0], STDIN_FILENO) == -1) {
            perror("Error redirecting stdin");
            exit(EXIT_FAILURE);
        }

        // 3. 关闭原来的管道读端(已经通过dup2复制到stdin了)
        close(fd[0]);

        // 4. 调用more命令,这里用execlp更方便
        execlp("more", "more", NULL);
        // 如果execlp返回,说明调用失败
        perror("Error executing more");
        exit(EXIT_FAILURE);
    } else {
        // 父进程逻辑:写100行数据到管道
        // 1. 关闭不需要的读端(父进程只需要写数据)
        close(fd[0]);

        // 2. 写入100行内容
        char buf[100];
        for (int i = 0; i < 100; i++) {
            snprintf(buf, sizeof(buf), "这是第%d行测试内容\n", i+1);
            write(fd[1], buf, strlen(buf));
        }

        // 3. 关键!写完后必须关闭写端,这样more才会收到EOF并退出
        close(fd[1]);

        // 4. 等待子进程执行完毕,避免僵尸进程
        waitpid(pid, NULL, 0);
    }

    return EXIT_SUCCESS;
}

关键步骤解释

  1. 管道两端的关闭策略:
    • 父进程只需要写,所以fork后立刻关闭读端fd[0];写完数据后必须关闭写端fd[1],这是让more退出的核心——否则more会一直等新数据,程序就冻结了。
    • 子进程只需要读,所以fork后立刻关闭写端fd[1];重定向stdin后关闭原来的读端fd[0],避免文件描述符泄漏。
  2. 标准输入重定向:用dup2(fd[0], STDIN_FILENO)把管道的读端绑定到stdin,这样more就会从管道读取数据,而不是终端输入。
  3. 等待子进程:父进程用waitpid等待子进程结束,确保程序流程正常,不会出现父进程先退出导致的异常。

你可以对照你的代码,看看是不是漏掉了这些关键步骤——尤其是写完数据后关闭写端这一步,我当初就是因为忘了这个,卡了快半小时!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:34:55