首页 文章

使用pipe()系统调用

提问于
浏览
5

我一直在尝试使用pipe()系统调用来创建一个支持管道的shell(使用任意数量的命令) .

不幸的是,我使用pipe()并没有太多运气 . 在花了几天时间查看各种在线资源后,我决定整理一个过度简化的程序,该程序与执行 ls | sort 具有相同的效果,看看我是否能够为两个兄弟,子进程工作 . 这是代码:

#include <sys/wait.h>
#include <unistd.h>

void run(char *cmd) {
   char *args[2];
   args[0] = cmd;
   args[1] = NULL;

   execvp(cmd, args);
}

int main(void) {
    int filedes[2];
    pipe(filedes);

    pid_t pid_a, pid_b;

    if (!(pid_a = fork())) {
        dup2(filedes[1], 1);
        run("ls");
    }

    if (!(pid_b = fork())) {
        dup2(filedes[0], 0);
        run("sort");
    }

    waitpid(pid_a, NULL, 0);
    waitpid(pid_b, NULL, 0);

    return 0;
}

管道是在父级中创建的,我知道在execvp()调用之后,每个子进程都继承了pipe()在父级中创建的文件描述符 . 对于 ls 进程,我使用dup2()将其标准输出(1)重定向到管道的写入端,对于 sort 进程,将标准输入(0)重定向到管道的读取端 .

最后,我等待两个进程完成后再退出 .

我的直觉告诉我这应该有效,但事实并非如此!

有什么建议?

4 回答

  • 6

    在父进程中调用 waitpid 之前,必须从管道中关闭所有不需要的文件描述符 . 这些是:

    • filedes[0] in pid_a
      809 filedes[1] in pid_b

    • 父进程中的 filedes[0]filedes[1]

    您还应该检查 pipe()fork() 没有返回 -1 ,这意味着发生了错误 .

  • 1

    你必须关闭你不使用的管道 . 至少 sort 将从stdin读取,直到stdin关闭 .

    在这种情况下,它的stdin永远不会关闭,因为你仍然有2个打开的文件描述符 .

    在ls孩子中

    • filedes [0](这可能在ls结束时关闭)
      父程序中的
    • filedes [0](由于waitpid()因为排序结束而永远不会关闭,但它永远不会因为父进程保持stdin打开而关闭)

    将您的计划更改为

    if (!(pid_a = fork())) {
        dup2(filedes[1], 1);
        closepipes(filedes);
        run("ls");
    }
    
    if (!(pid_b = fork())) {
        dup2(filedes[0], 0);
        closepipes(filedes);
        run("sort");
    }
    closepipe(filedes);
    waitpid(pid_a, NULL, 0);
    waitpid(pid_b, NULL, 0);
    

    密封管就像是

    void closepipes(int *fds)
    { 
     close(fds[0]);
     close(fds[1]);
    }
    
  • 4

    您需要关闭(至少)父进程中管道的写入端 . 否则,管道的读取端将永远不会读取EOF状态, sort 将永远不会完成 .

  • 3

    这段代码工作正常......

    #include <sys/wait.h>
        #include <unistd.h>
        using namespace std;
    
        void run(char *cmd) {
           char *args[2];
           args[0] = cmd;
           args[1] = NULL;
    
           execvp(cmd, args);
        }
        void closepipe(int *fds)
        { 
         close(fds[0]);
         close(fds[1]);
        }
    
        int main(int argc,char *argv[]) {
    
            int filedes[2];
            pipe(filedes);
            char lss[]="ls";
            char sorts[]="sort";
            pid_t pid_a, pid_b;
         chdir(argv[1]);
        if (!(pid_a = fork())) {
            dup2(filedes[1], 1);
            closepipe(filedes);
            run(lss);
        }
    
        if (!(pid_b = fork())) {
            dup2(filedes[0], 0);
            closepipe(filedes);
            run(sorts);
        }
        closepipe(filedes);
        waitpid(pid_a, NULL, 0);
        waitpid(pid_b, NULL, 0);
    
            return 0;
        }
    

相关问题