【问题标题】:piping two times using fork in C linux在 C linux 中使用 fork 管道两次
【发布时间】:2013-01-11 23:56:18
【问题描述】:

我正在尝试重写一个执行类似 ls|wc|wc 的 c 程序,我已经为 ls|wc 完成了它,它工作得很好,但我无法弄清楚为什么我的程序在指定的孩子处停止线。请帮忙!

int main (void)
{
    pid_t pid_fils, pid_pfils;

    int fd[2], fd2[2];

    if(pipe(fd)==-1 || pipe(fd2)==-1)
    {
        printf("pipe failed!");
        return 1;
    }

    printf("program started\n");
    pid_fils=fork();
    if(pid_fils==0)
    {
        pid_pfils=fork();
        if(pid_pfils==0)
        {
            //action3
            printf("I am the grandson\n");
            close(fd[0]);//close read side
            dup2(fd[1],1);//connect write with stdout
            close(fd[1]);//close write side
            execlp("ls","ls",(char*)0);
            //execvp("ls",argv3);
            return 0;/*actions grandson*/
        }
        else
        {
            //action2
            printf("I am the son\n");
            wait();
            printf("son, wait ok\n");
            >close(fd[1]);  //close read side
            >dup2(fd[0],0); //connect write with stdin
            >close(fd[0]);  //close read side

            ///////pipe2////
           > close(fd2[0]);  //close read side
            >dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/
            printf("ok!\n");    
            >close(fd2[1]);  //close write side

            execlp("wc","wc",(char*)0);
            printf("error exec returned!\n");    
            return 0;
        }
    }
    else
    {
        ///action1
        printf("I am the parent\n");
        wait();
        printf("parent,wait ok\n");
        close(fd2[1]);  //close write side, 
        dup2(fd2[0],0); //connect read with stdin
        close(fd2[0]);  //close read side
        execlp("wc","wc",(char*)0);
        return 0;/*the parent*/
    }
    return 1;
}

【问题讨论】:

  • 请修剪您的代码以仅包含相关部分。
  • 使用fprintf( stderr, ... 将所有内容打印到stderr。这将有助于确保您的诊断不会进入管道。并且总是将错误消息写入标准错误。例如,perror( "pipe failed" )printf("pipe failed" ) 有用得多

标签: c linux ubuntu pipe systems-programming


【解决方案1】:

确保关闭所有未使用的描述符。在您的情况下,最简单的解决方案是将 pipe(fd) 的创建移动到第一个 if 块中(在第一个子进程中)。问题是,只要任何进程都可能写入管道,阅读器就不会得到 EOF,因此不会终止。

if(pipe(fd2)==-1)
{
    printf("pipe failed!");
    return 1;
}

printf("program started\n");
pid_fils=fork();
if(pid_fils==0)
{
    if(pipe(fd)==-1)
    {
        printf("pipe failed!");
        return 1;
    }
    pid_pfils=fork();

我还应该提到,您可能需要重新考虑等待呼叫。不确定您打算对它们做什么,但您不希望“ls”进程阻塞输出,因为阅读器尚未启动。

【讨论】:

    【解决方案2】:
    dup2(fd2[1],1);
    

    上面一行将首先关闭描述符 1 处的文件,然后将描述符从 fd2[1] 复制到 1。

    1 是标准输出。这意味着调用关闭标准输出。

    printf 打印到 stdout,意味着 printf 打印到现在分配给管道 fd2 的 1

    所以你的 ok 进入了管道,而不是在屏幕上。

    试试

            //action2
            printf("I am the son\n");
            wait();
            printf("son, wait ok\n");
            close(fd[1]);  //close read side
            dup2(fd[0],0); //connect write with stdin
            close(fd[0]);  //close read side
    
            ///////pipe2////
            int my_terminal_out = dup(1);
            close(fd2[0]);  //close read side
            dup2(fd2[1],1); //connect write with stdout/*it stops here -can't display "ok!"*/
            fprintf(my_terminal_out, "ok!\n");    
            close(fd2[1]);  //close write side
    

    未测试。此外,您还应该测试其余代码是否存在类似的错误。

    +DrC 说的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-01-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多