【问题标题】:Implement piping ("|") using C..(fork used)使用 C 实现管道(“|”)..(使用 fork)
【发布时间】:2011-01-12 13:56:59
【问题描述】:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>

int main(int argc,char **argv)
{
    int fd[2];
    pid_t childpid;
    pipe(fd);
    childpid=fork();
    if (childpid == -1)
    {
        perror("Error forking...");
        exit(1);
    }
    if (childpid)   /*parent proces*/   //grep .c
    {
        wait(&childpid);        //waits till the child send output to pipe
        close(fd[1]);
        close(0);       //stdin closed
        dup2(fd[0],0);
        execlp(argv[2],argv[2],argv[3],NULL);

    }
    if (childpid==0)  //ls
    {
        close(fd[0]);   /*Closes read side of pipe*/
        close(1);       //STDOUT closed
        dup2(fd[1],1);
        execl(argv[1],NULL);
    }
    return 0;
}

如果我将命令行参数指定为“ls grep .c”,我应该会显示所有“.c”文件。

伪代码:- 我的子进程将运行“ls”而父进程将运行“grep .c”.. 父进程等待子进程完成,以便子进程写入管道。

试运行:-

bash-3.1$ ls | grep .c
1.c
hello.c
bash-3.1$ ./a.out ls grep .c
bash-3.1$

为什么会这样?

【问题讨论】:

  • 好的。我自己得到了答案。我在子进程中使用了“execl()”,它不使用 $PATH 环境变量搜索文件名....如果我更改为 execlp(),程序将按预期运行。
  • 你可能也不想要那个“wait(&childpid);” (或其不准确的评论)在那里。它不会等到数据来自子进程,而是等到子进程状态发生变化 - 例如出口。如果您的子进程写入的数据超过管道的价值(可能是 8k),它将挂起等待父进程读取,而父进程仍在等待它退出。
  • 那么,我应该怎么做才能让父级在子级执行后执行......?
  • read(2) 从父端将阻塞,直到有数据或 EOF。管道的全部意义在于两个程序同时运行。
  • 为了更简洁的代码,不要使用三重 if 语句(不需要它并添加额外的计算)你要么是失败的 fork,要么是孩子,要么是父母,所以 if ((childpid = fork() ) == -1) {...} else if(childpid == 0) {...} else{...}

标签: c gcc pipe fork


【解决方案1】:

一个简单的错误:您的execl 调用实际上应该是execlp。此外,您可以摆脱 waitclose 语句。然后你应该检查execlp的错误代码。

【讨论】:

  • 你不需要测试exec*()函数的返回状态;如果函数返回,则失败。但是你是对的,应该对失败的exec*() 函数进行某种错误处理。
【解决方案2】:

还有一点,close(0)close(1) 是不必要的,dup2() 函数会自动为您完成。

【讨论】:

  • 你是对的。如果代码使用dup() 而不是dup2(),则close(0)close(1) 将是相关的。
【解决方案3】:

有关实现管道的代码,请参考以下问题中的答案。

Pipe implementation in Linux using c

【讨论】:

    猜你喜欢
    • 2014-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-08
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多