管道bash命令将回声和BC复制到C程序中

时间:2019-05-17 13:36:21

标签: c pipe fork dup2 execl

我正在尝试执行一些C语言程序,以实现两个bash命令的管道:echo $ arithmeticOperation |公元前

$ arithmeticOperation是一个字符串作为输入。

程序在执行第一个命令时工作正常,但是当我运行第二个命令时,我得到了正确的输出,但是执行bc的子进程仍然卡住,阻止了子进程结束。

因此,在这一行中,父进程被阻止:                waitpid(pid2,NULL,0);

您认为问题可能出在哪里?

对不起,如果我问错了问题,这是我的第一个问题。谢谢。



    #define SYSCALL(r,c,e) if((r=c)==-1) { perror(e);exit(EXIT_FAILURE);}

    int main(){
        char buf[128];
        int pfd[2],err;
        pid_t pid1,pid2;
        SYSCALL(err,pipe(pfd),"pipe");
        switch (pid1=fork()) {
            case -1: { perror("fork"); exit(EXIT_FAILURE);}
            case 0 : { 
                scanf("%s",buf);
                SYSCALL(err,dup2(pfd[1],1),"dup");
                close(pfd[1]);
                close(pfd[0]);
                execl("/bin/echo","echo",buf,(char *)NULL);
                return 1;
            }   
        }   
        switch (pid2=fork() ){
             case -1 : { perror("fork"); exit(EXIT_FAILURE);}
             case 0 : { 
                 SYSCALL(err,dup2(pfd[0],0),"dup");
                 close(pfd[1]);
                 close(pfd[0]);
     //          execl("/usr/bin/bc","bc",(char *)NULL);
                 execlp("bc","bc",(char *)NULL);
                return 1;
            }   
        }   
    printf("waiting . . . \n");
    waitpid(pid1,NULL,0);
    printf("wait\n");
    waitpid(pid2,NULL,0);
    close(pfd[1]);
    close(pfd[0]);
    return 0;
    }

因此,如果我将“ 1 + 1”作为输入字符串,则可以得到正确的输出,但是执行bc的进程永远不会退出

1 个答案:

答案 0 :(得分:0)

正如我在comment中所指出的那样,您的父进程必须在等待bc之前关闭 管道的文件描述符(并且您已经同意,此修复程序可以修复问题)。

之所以出现这种情况,是因为bc的管道打开以供读取,而父级的管道打开以供写入,并且内核认为父级因此可以将数据发送到bc。不会,但是可以。

在管理管道时必须非常小心。您仔细避免了通常的问题,即在子级中没有关闭足够的文件描述符。


经验法则:如果您 dup2() 管道的一端到标准输入或标准输出,同时关闭两个 由返回的原始文件描述符 pipe() 尽快地。 特别是,在使用任何 exec*() 系列功能。

如果您将描述符与任何一个重复,则该规则也适用 dup() 要么 fcntl()F_DUPFD


我也需要扩展它以涵盖父进程。

如果父进程不打算通过管道与它的任何子进程进行通信,则必须确保其关闭管道的两端,以便其子进程可以在读取时接收EOF指示(或获取SIGPIPE信号或写入错误)而不是无限期地阻塞。父级通常应该关闭管道的至少一端,这对于程序在单个管道的两端进行读写是非常不寻常的。