Вход/Регистрация
Linux программирование в примерах
вернуться

Роббинс Арнольд

Шрифт:

В нашем случае после порождения двух потомков имеются три процесса, у каждого из которых есть копии двух дескрипторов файлов каналов: родительский и два порожденных. Родительский процесс закрывает оба конца, поскольку ему не нужен канал. Левый потомок записывает в канал, поэтому ему нужно закрыть читаемый конец. Правый потомок читает из канала, поэтому ему нужно закрыть записываемый конец. Это оставляет открытым ровно по одной копии дескриптора файла.

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

Следующая программа,

ch09-pipeline.c
, создает эквивалент следующего конвейера оболочки:

$ echo hi there | sed s/hi/hello/g

hello there

Вот программа:

1 /* ch09-pipeline.c --- ответвляет два процесса в их собственный конвейер.

2 Для краткости проверка ошибок сведена к минимуму. */

3

4 #include <stdio.h>

5 #include <errno.h>

6 #include <sys/types.h>

7 #include <sys/wait.h>

8 #include <unistd.h>

9

10 int pipefd[2];

11

12 extern void left_child(void), right_child(void);

13

14 /* main --- порождение процессов и ожидание их завершения */

15

16 int main(int argc, char **argv)

17 {

18 pid_t left_pid, right_pid;

19 pid_t ret;

20 int status;

21

22 if (pipe(pipefd) < 0) { /* создать канал в самом начале */

23 perror("pipe");

24 exit(1);

25 }

26

27 if ((left_pid = fork) < 0) { /* порождение левого потомка */

28 perror("fork");

29 exit(1);

30 } else if (left_pid == 0)

31 left_child;

32

33 if ((right_pid = fork) < 0) { /* порождение правого потомка */

34 perror("fork");

35 exit(1);

36 } else if (right_pid == 0)

37 right_child;

38

39 close(pipefd[0])); /* закрыть родительские копии канала */

40 close(pipefd[1]);

41

42 while ((ret = wait(&status)) > 0) { /* wait for children */

43 if (ret == left_pid)

44 printf("left child terminated, status: %x\n", status);

45 else if (ret == right_pid)

46 printf("right child terminated, status: %x\n", status);

47 else

48 printf("yow! unknown child %d terminated, status %x\n",

49 ret, status);

50 }

51

52 return 0;

53 }

Строки 22–25 создают канал. Это должно быть сделано в самом начале.

Строки 27–31 создают левого потомка, а строки 33–37 создают правого потомка. В обоих случаях родитель продолжает линейное исполнение ветви

main
до тех пор, пока порожденный процесс не вызовет соответствующую функцию для манипулирования дескрипторами файла и осуществления
exec
.

Строки 39–40 закрывают родительскую копию канала.

Строки 42–50 в цикле ожидают потомков, пока

wait
не вернет ошибку.

55 /* left_child --- осуществляет работу левого потомка */

56

57 void left_child(void)

58 {

59 static char *left_argv[] = { "echo", "hi", "there", NULL };

60

61 close(pipefd[0]);

62 close(1);

63 dup(pipefd[1]);

64 close(pipefd[1]);

  • Читать дальше
  • 1
  • ...
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: