Как обрабатывать логическую цепочку фильтров команд оболочки? - PullRequest
0 голосов
/ 15 февраля 2019

Я читал книгу «Операционные системы» и нашел, что этот пример работает.Я понял, что делает ps -elf | less.| (труба) работает как мост между командами ps -elf и less и принимает вывод ps -elf в качестве ввода для less.

Но, углубляясь в команды оболочки, я пытаюсь понять, что будет

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 голосов
/ 15 февраля 2019

При создании каналов вам нужно начать с команды 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 */
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...