【问题标题】:exec() and pipe() between child process in CC中子进程之间的exec()和pipe()
【发布时间】:2018-05-25 20:46:22
【问题描述】:

我正在尝试使用 pipe()fork() 来实现这一点:

ls |厕所

首先我检查了管道是否工作正常,这是代码。

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

int main(void){

    char *param1[]={"ls",NULL};
    char *param2[]={"wc",NULL};

    int p[2];
    pipe(p);

    pid_t process1, process2;

    if((process1=fork())==0){ // child 1
        dup2(p[1],1); // redirect stdout to pipe
        close(p[0]);
        execvp("ls", param1);
        perror("execvp ls failed");
    }
    else if(process1>0){ // parent
        wait(NULL);
    }

    if((process2=fork())==0){ // child 2
        dup2(p[0],0); // get stdin from pipe
        close(p[1]);

        char buff[1000]={0};
        read(STDIN_FILENO,buff,250);
        printf("---- in process2 -----\n%s\n",buff);
    }
    else if(process2>0){ // parent
        wait(NULL);
    }
    return 0;
}

我检查它工作正常。我把read()printf()换成了exec(),比如:

if((process2=fork())==0){ // child 2
    dup2(p[0],0); // get stdin from pipe
    close(p[1]);

    execvp("wc",param2);
    perror("execvp wc failed");
}

我的终端挂了。我认为wc 进程没有得到任何输入。所以我的问题是,为什么read()printf() 有效,而execvp() 无效?

【问题讨论】:

  • 这里有什么问题?
  • 如果第一个进程启动失败,您没有错误处理!此外,您是否尝试在 两个 都执行后等待进程(防止管道满载)?
  • @potato 我解决了我的问题,谢谢
  • 只是一个建议:如果你使用STDIN_FILENO 来代替read,那么你也可以使用这些宏来代替dup2...如果你只提供一个大小为1000 的缓冲区还是使用 250 字节?宁愿选择以 2 的幂为单位的缓冲区大小(1024、256、...)。

标签: c linux pipe fork exec


【解决方案1】:

您无需等待每次创建新进程并关闭父进程中的描述符,例如:

if((process1=fork())==0){ // child 1
    dup2(p[1],1); // redirect stdout to pipe
    close(p[0]);
    execvp("ls", param1);
    perror("execvp ls failed");
}
else if(process1==-1){ // fork failed
    exit(1);
}
close(p[1]); // no need for writing in the parent

if((process2=fork())==0){ // child 2
    dup2(p[0],0); // get stdin from pipe

    char buff[1000]={0};
    read(STDIN_FILENO,buff,250);
    printf("---- in process2 -----\n%s\n",buff);
}
else if(process2==-1){ // second fork failed
    close(p[0]); // ensure there is no reader to the pipe
    wait(NULL); // wait for first chidren
    exit(1);
}
close(p[0]); // no need for reading in the parent

wait(NULL);
wait(NULL); // wait for the two children

【讨论】:

  • 谢谢,它有效。我有一个问题:close() 有必要吗?我可以检查我是否没有使用close(),它不起作用
  • @wanttobepro close()wc 的输入中是必需的,因为它知道停止计算单词。
  • @wanttobepro 正如 Jeremy 所说,关闭父级是必要的,管道语义是为了提供两端之间的同步,所以如果你不关闭它可能会发生孩子认为有其他人在管道的另一端。
猜你喜欢
  • 1970-01-01
  • 2013-10-12
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-23
  • 2010-12-22
相关资源
最近更新 更多