Чтение онлайн

на главную

Жанры

Linux программирование в примерах

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

Шрифт:

При наличии правила «возвращения наименьшего неиспользуемого номера» в сочетании с функцией

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

1. Создать канал с помощью

pipe
. Это должно быть сделано сначала, чтобы два порожденных процесса могли унаследовать дескрипторы открытых файлов.

2. Создать то, что мы называем «левым потомком». Это процесс, стандартный

вывод которого идет в канал. В данном процессе сделать следующее:

 a. Использовать '

close(pipefd[0])
', поскольку читаемый конец канала в левом потомке не нужен.

 b. Использовать '

close(1)
', чтобы закрыть первоначальный стандартный вывод.

 c. Использовать '

dup(pipefd[1])
' для копирования записываемого конца канала в дескриптор файла 1.

 d. Использовать '

close(pipefd[1])
', поскольку нам не нужны две копии открытого дескриптора.

 e. Выполнить

exec
для запускаемой программы.

3. Создать то, что мы называем «правым потомком». Это процесс, стандартный ввод которого поступает из канала. Шаги для этого потомка являются зеркальным отражением шагов для левого потомка:

 a. Использовать '

close(pipefd[1])
', поскольку записываемый конец канала в правом потомке не нужен.

 b. Использовать '

close(0)
', чтобы закрыть первоначальный стандартный ввод.

 c. Использовать '

dup(pipefd[0])
' для копирования читаемого конца канала в дескриптор файла 0.

 d. Использовать '

close(pipefd[0])
', поскольку нам не нужны две копии открытого дескриптора.

 e. Выполнить

exec
для запускаемой программы.

4. В родителе закрыть оба конца канала — '

close(pipefd[0]); close(pipefd[1])
'.

5. Наконец, использовать в родителе

wait
для ожидания завершения обоих порожденных процессов.

Обратите внимание, как важно закрыть неиспользуемые копии дескрипторов файлов каналов. Как мы отмечали ранее, файл не закрывается до тех пор, пока не будет закрыт последний открытый для него дескриптор. Это верно, даже если дескрипторы файлов разделяют несколько процессов. Закрытие не использующихся дескрипторов файлов имеет значение, поскольку процесс, читающий из канала, не получит указания конца файла, пока все копии записываемого конца не будут закрыты.

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

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

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

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);

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

Сильнейший Столп Империи. Книга 3

Ермоленков Алексей
3. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 3

Последний Паладин. Том 10

Саваровский Роман
10. Путь Паладина
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Последний Паладин. Том 10

Викинг

Мазин Александр Владимирович
1. Викинг
Приключения:
исторические приключения
8.92
рейтинг книги
Викинг

Запечатанный во тьме. Том 3

NikL
3. Хроники Арнея
Фантастика:
уся
эпическая фантастика
фэнтези
5.00
рейтинг книги
Запечатанный во тьме. Том 3

Gloster Gladiator

Иванов С. В.
72. Война в воздухе
Научно-образовательная:
история
военная техника и вооружение
военная история
5.00
рейтинг книги
Gloster Gladiator

Последний Паладин. Том 8

Саваровский Роман
8. Путь Паладина
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Последний Паладин. Том 8

Шатун. Лесной гамбит

Трофимов Ерофей
2. Шатун
Фантастика:
боевая фантастика
7.43
рейтинг книги
Шатун. Лесной гамбит

Я еще не бог. Книга XXXV

Дрейк Сириус
35. Дорогой барон!
Фантастика:
аниме
попаданцы
5.00
рейтинг книги
Я еще не бог. Книга XXXV

Сильнейший Столп Империи. Книга 2

Ермоленков Алексей
2. Сильнейший Столп Империи
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Сильнейший Столп Империи. Книга 2

Хозяин Стужи 6

Петров Максим Николаевич
6. Злой Лед
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Хозяин Стужи 6

Мы друг друга не выбирали

Кистяева Марина
1. Мы выбираем...
Любовные романы:
остросюжетные любовные романы
прочие любовные романы
современные любовные романы
5.00
рейтинг книги
Мы друг друга не выбирали

Ваше Сиятельство 2

Моури Эрли
2. Ваше Сиятельство
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Ваше Сиятельство 2

Настольная книга по теологии. Библейский комментарий АСД Том 12

Церковь христиан адвентистов седьмого дня
Научно-образовательная:
религиоведение
5.00
рейтинг книги
Настольная книга по теологии. Библейский комментарий АСД Том 12

Мастер 11

Чащин Валерий
11. Мастер
Фантастика:
боевая фантастика
попаданцы
технофэнтези
аниме
фэнтези
5.00
рейтинг книги
Мастер 11