[<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
 Программные каналы - Пример - who | sort

В этом примере создаются два подпроцесса, взаимодействующие через
канал. Каждый из этих процессов исполняет свою программу, а
родительский процесс ждет их завершения.

9-11      До запуска подпроцессов создается канал.

12-20     Здесь создается  первый подпроцесс.  Его  стандартный  вывод
          перенаправляется на  входной  конец  канала.  Весь  вывод  в
          дескриптор файла  1 будет направлен в канал. Это относится к
          printf(3C)  так   же,  как  и  к  любому  выводу  программы,
          запущенной  системным  вызовом  exec(2).  Затем  исполняется
          команда  who(1).   fflush(stdout)   делается,   чтобы   быть
          уверенным, что  буферизованный  текст  будет  выведен  перед
          вызовом exec(2), а не потерян.
21-30     Создается  второй   подпроцесс,  и   eго  стандартный   ввод
          перенаправляется на выходной конец канала. Стандартный ввод,
          дескриптор файла  0, этого  процесса, теперь  будет идти  из
          выходного конца  канала. Функция read_to_nl(), не показанная
          здесь, читает  из файлового  дескриптора 0,  пока не получит
          символ конца  строки. Эта  функция, как  и любая  программа,
          запущенная exec(2), будет получать ввод из канала.
28        fflush(stdout) нужен  только если вывод whos3 перенаправлен.
          Вывод на терминал буферизуется по строкам.
31        Родительский процесс  должен закрыть  оба конца канала, если
          не использует  его. Если  входной конец  закрыт, то читающий
          процесс, sort(1)  в этом  примере, увидит конец файла, когда
          единственный пишущий процесс who(1) закроет свой стандартный
          вывод. Иначе  читающий процесс  будет висеть,  ожидая ввода,
          который никогда  не поступит. Выходной конец закрывается для
          удобства пишущего  процесса who(1),  который получит SIGPIPE
          при попытке  записи,  если  все  читающие  процессы  закрыли
          выходной конец.  Замечание: exit(2)  закрывает все  открытые
          дескрипторы файлов.
32-33     Родительский процесс  ожидает завершения  обоих порожденных,
          но выходной статус завершившегося процесса игнорируется.

Эта программа работает так:

$ whos3
Heading: who display sorted
bern      tty26     May  8    18:14
console   console   May  5    22:47
ipd       tty31     May  8    07:46

Файл: whos3.c
                    ПРОГРАММНЫЕ КАНАЛЫ - ПРИМЕР -
                              who | sort

 1   #include <sys/types.h>
 2   #include <stdio.h>
 3   #include <unistd.h>
 4   #include <wait.h>
 5   char text[80];
 6   main(int argc, char **argv)
 7   {
 8       int fd[2]; void read_to_nl(char *);
 9       if (pipe(fd) == -1) {
10           perror(argv[0]); exit(1);
11       }
12       if (fork() == 0) { /* first child */
13           close(1);
14           dup(fd[1]); /* redirect std output */
15           close(fd[0]); close(fd[1]);
16           printf("who display sorted\n");
17           fflush(stdout);
18           execl("/bin/who", "who", (char *) 0);
19           exit(127);
20       }
21       if (fork() == 0) { /* second child */
22           close(0);
23           dup(fd[0]); /* redirect std input */
24           close(fd[0]); close(fd[1]);
25           read_to_nl(text);
26           printf("\tHeading: %s\n", text);
27           fflush(stdout);
28           execl("/bin/sort","sort", (char *)0);
29           exit(127);
30       }
31       close(fd[0]);close(fd[1]);
32       while (wait((int *) 0) != -1)
33           ;       /* null */
34       exit(0);
35   }

...