Shell如何以编程方式实现管道?

时间:2014-02-26 11:01:44

标签: linux

我理解I / O重定向在Unix / Linux中是如何工作的,我知道Shell使用此功能来管理具有特殊类型文件的程序 - 匿名管道。但我想知道Shell如何以编程方式实现它的细节?我不仅对所涉及的系统调用感兴趣,而且对整个画面感兴趣。

例如ls | sort,Shell如何为lssort执行I / O重定向?

2 个答案:

答案 0 :(得分:3)

整个画面很复杂,最好的理解方法是研究一个小壳。对于有限的图片,这里是。在执行任何操作之前,shell会解析整个命令行,以便确切知道如何链接进程。让我们说它遇到了proc1 | PROC2。

  • 它设置了一个管道。长话短说,写入thepipe[0]最终会出现在thepipe[1]

    int thepipe[2];
    pipe(thepipe);
    
  • 它会在exec

    之前分配第一个进程并更改其标准输出的方向
    dup2 (thepipe[1], STDOUT_FILENO);
    
  • 它执行新程序,该程序幸福地不知道重定向,只是写入stdout,就像一个表现良好的过程

  • 它分叉第二个进程并在exec

    之前更改其标准输入源的来源
    dup2 (thepipe[0], STDIN_FILENO);
    
  • 它执行新程序,不知道其输入来自另一个程序

像我说的那样,这是一幅有限的画面。在真实的图片中,外壳以菊花链形式将它们链接在一个环路中,并且还记得在适当的时刻关闭管道末端。

答案 1 :(得分:1)

这是来自silberschatz的书籍操作系统概念的示例程序

如果你知道fork()和相关的东西的概念,程序是不言自明的......希望这有帮助! (如果你还想要解释,我可以解释一下!)

显然,如果你想让它像

那样工作,你应该在这个程序中做一些更改(例如fork()等的更改)

ls | sort

 #include <unistd.h>
    #include <stdio.h>
    #include <string.h>
    #include <sys/types.h>

    #define BUFFER SIZE 25
    #define READ END 0
    #define WRITE END 1
    int main(void)
    {
    char write msg[BUFFER SIZE] = "Greetings";
    char read msg[BUFFER SIZE];
    int fd[2];
    pid t pid;

    /* create the pipe */
    if (pipe(fd) == -1) {
    fprintf(stderr,"Pipe failed");
    return 1;
    }
    /* fork a child process */
    pid = fork();
    if (pid < 0) { /* error occurred */
    fprintf(stderr, "Fork Failed");
    return 1;
    }
    if (pid > 0) { /* parent process */
    /* close the unused end of the pipe */
    close(fd[READ END]);
    /* write to the pipe */
    write(fd[WRITE END], write msg, strlen(write msg)+1);
    /* close the write end of the pipe */
    close(fd[WRITE END]);
    }
    else { /* child process */
    /* close the unused end of the pipe */
    close(fd[WRITE END]);
    /* read from the pipe */
    read(fd[READ END], read msg, BUFFER SIZE);
    printf("read %s",read msg);
    }
    }
    /* close the write end of the pipe */
    close(fd[READ END]);
    return 0;
    }