如何处理Shell命令过滤器的逻辑链?

时间:2019-02-15 15:19:44

标签: c shell operating-system

我正在阅读《操作系统》一书,发现该示例可以正常工作。我了解ps -elf | less在做什么。 |(管道)充当ps -elfless命令之间的桥梁,并且将ps -elf的输出作为less的输入。

但是要深入了解shell命令,我想了解会是什么

ps -elf | grep "/usr" | wc –l可以吗?

在这种情况下,有两个|(管道),逻辑相同。但是我无法将其实现为一个有效的示例。如果您知道该怎么做,这对我来说很清楚。

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <unistd.h>

int main()
{
    int fds[2];
    char buf[30];
    pid_t pid1, pid2, pid;
    int status, i;

    /* create a pipe */
    if (pipe(fds) == -1) {
            perror("pipe");
            exit(1);
    }

    /* fork first child */
    if ( (pid1 = fork()) < 0) {
    perror("fork");
    exit(1);
    }

    if ( pid1 == 0 ) {
        close(1);  /* close normal stdout (fd = 1) */
        dup2(fds[1], 1);   /* make stdout same as fds[1] */
        close(fds[0]); /* we don't need the read end -- fds[0] */

        if( execlp("ps", "ps", "-elf", (char *) 0) < 0) {
        perror("Child");
        exit(0);
    }

    /* control never reaches here */
    } 

    /* fork second child */
    if ( (pid2 = fork()) < 0) {
    perror("fork");
    exit(1);
    }

    if ( pid2 == 0 ) {
        close(0);   /* close normal stdin (fd = 0)*/
        dup2(fds[0],0);   /* make stdin same as fds[0] */
        close(fds[1]); /* we don't need the write end -- fds[1]*/

        if( execlp("less", "less", (char *) 0) < 0) {
        perror("Child");
        exit(0);
    }

    /* control never reaches here */
    }

    /* parent doesn't need fds  - MUST close - WHY? */
    close(fds[0]); 
    close(fds[1]); 

    /* parent waits for children to complete */
    for( i=0; i<2; i++) {
        pid = wait(&status);
        printf("Parent: Child %d completed with status %d\n", pid, status);
    }
}

Output for the program

1 个答案:

答案 0 :(得分:2)

在创建管道时,您需要从管道中的 last 命令开始,然后从该命令反向进行。这样,您启动的每个程序都在等待管道中先前命令的输出。如果从头开始,则第一个程序可以在有机会启动第二个程序之前完成,从而导致管道被关闭。

在这种情况下,您首先运行less。这就是在等待尚未出现的输出。然后,您运行ps,其输出将馈送到less

/* fork first child */
if ( (pid1 = fork()) < 0) {
    perror("fork");
    exit(1);
}

if ( pid1 == 0 ) {
    close(0);   /* close normal stdin (fd = 0)*/
    dup2(fds[0],0);   /* make stdin same as fds[0] */
    close(fds[1]); /* we don't need the write end -- fds[1]*/

    if( execlp("less", "less", (char *) 0) < 0) {
        perror("Child");
        exit(0);
    }

    /* control never reaches here */
} 

/* fork second child */
if ( (pid2 = fork()) < 0) {
    perror("fork");
    exit(1);
}

if ( pid2 == 0 ) {
    close(1);  /* close normal stdout (fd = 1) */
    dup2(fds[1], 1);   /* make stdout same as fds[1] */
    close(fds[0]); /* we don't need the read end -- fds[0] */

    if( execlp("ps", "ps", "-elf", (char *) 0) < 0) {
        perror("Child");
        exit(0);
    }

    /* control never reaches here */
}