2012-07-07 3 views
1

ссылаясь на старый вопрос о домашней задаче: /* implementing "/usr/bin/ps -ef | /usr/bin/more" */ с использованием труб.Как execv получает выход из трубы?

#include <stdio.h> 
#include <unistd.h> 
#include <stdlib.h> 

int main() 
{ 
    int fds[2]; 
    int child[2]; 
    char *argv[3]; 
    pipe(fds); 
    if (fork()== 0) { 
    close(fds[1]); 
    close(STDIN_FILENO); dup(fds[0]); /* redirect standard input to fds[1] */ 
    argv[0] = "/bin/more"; 
    argv[1] = NULL;   /* check how the argv array is set */ 
    execv(argv[0], argv);// here how execv reads from stdin ?? 
    exit(0); 


    } 
    if (fork() == 0) { 
    close(fds[0]); 
    close(STDOUT_FILENO); dup(fds[1]); /* redirect standard output to fds[0] */ 
    argv[0] = "/bin/ps"; 
    argv[1] = "-e"; argv[2] = NULL; 
    execv(argv[0], argv); 
    exit(0); 

    } 

    close(fds[1]); 
    wait(&child[0]); 
    wait(&child[0]); 
} 

После перенаправления fd на стандартный вывод, как работает execv от него. Является ли встроенным в execv, что он читает со стандартного ввода перед выполнением команды? Я не могу получить эту концепцию.

ответ

1

Ваш вопрос основан на ложном посылке - execv не читает нигде и не нуждается. Это more, который читается с stdin, он наследует по вызову execv. Причина, по которой more читается с stdin, заключается в том, что это фильтр и, как и большинство фильтров, по умолчанию используется для чтения от stdin, если другой источник ввода не указан в командной строке. (В противном случае, /usr/bin/ps -ef | /usr/bin/more не будет работать.)

+0

Спасибо, сэр! Правильно. Я думал не в том направлении. Теперь я понял. Вот почему команда типа «ps | ls» будет печатать только выходные данные ls. – dejavu

0

В вашем втором fork вызова, я хотел бы изменить код из этого:

if (fork() == 0) { 
    close(fds[0]); 

к этому:

close(fds[0]); 
    if (fork() == 0) { 

argv[1] для ps звонок должен быть -ef.

Все программы будут считываться с stdin, чтобы получить ввод терминала и записать в stdout, чтобы доставить данные на терминал, если они ничего не делают, чтобы изменить настройки по умолчанию для этих потоков. Что делает код, это изменение stdin для more и изменение stdout для ps. stdout для more такой же, как и текущий процесс (родительский). Таким образом, ваша программа перенаправляет выходные данные терминалов ps на вход терминала для more.

Вызов pipe возвращает два файловых дескриптора, которые связаны друг с другом в одностороннем порядке. Когда ps пишет на свой stdout, он отправляется в dup d fds[1]. Когда more считывает из своего stdin, это dup d fds[0]. Итак, more поднимает вывод ps.

Смежные вопросы