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

на главную - закладки

Жанры

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

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

Шрифт:

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

65

66 execvp("echo", left_argv);

67 _exit(errno == ENOENT ? 127 : 126);

68 }

69

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

71

72 void right_child(void)

73 {

74 static char *right_argv[] = { "sed", "s/hi/hello/g", NULL };

75

76 close(pipefd[1]);

77 close(0);

78 dup(pipefd[0]);

79 close(pipefd[0]));

80

81 execvp("sed", right_argv);

82 _exit(errno == ENOENT ? 127 : 126);

83 }

Строки 57–68 являются кодом для левого потомка. Процедура следует приведенным выше шагам, закрывая ненужный конец канала, закрывая первоначальный стандартный вывод, помещая с помощью

dup
записываемый конец канала на номер 1 и закрывая затем первоначальный записываемый конец. В этот момент строка 66 вызывает
execvp
, и если она завершается неудачей, строка 67 вызывает
_exit
. (Помните, что строка 67 никогда не выполняется, если
execvp
завершается удачно.)

Строки 72–83 делают подобные же шаги для правого потомка. Вот что происходит при запуске:

$ ch09-pipeline /* Запуск программы */

left child terminated, status: 0 /* Левый потомок завершается до вывода (!) */

hello there /* Вывод от правого потомка */

right child terminated, status: 0

$ ch09-pipeline /* Повторный запуск программы */

hello there /* Вывод от правого потомка и ... */

right child terminated, status: 0 /* Правый потомок завершается до левого */

left child terminated, status: 0

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

кода, создающего несколько процессов, в особенности для кода, который вызывает семейство функций
wait
.

Весь процесс показан на рис. 9.5.

Рис. 9.5. Создание конвейера родителем

На рис. 9.5 (а) изображена ситуация после создания родителем канала (строки 22–25) и двух порожденных процессов (строки 27–37).

На рис. 9.5 (b) показана ситуация после закрытия родителем канала (строки 39–40) и начала ожидания порожденных процессов (строки 42–50). Каждый порожденный процесс поместил канал на место стандартного вывода (левый потомок, строки 61–63) и стандартного ввода (строки 76–78).

Наконец, рис. 9.5 (с) изображает ситуацию после закрытия потомками первоначального канала (строки 64 и 79) и вызова

execvp
(строки 66 и 81).

9.4.2. Создание нелинейных конвейеров:

/dev/fd/XX

Многие современные системы Unix, включая GNU/Linux, поддерживают в каталоге

/dev/fd
[98] специальные файлы. Эти файлы представляют дескрипторы открытых файлов с именами
/dev/fd/0
,
/dev/fd/1
и т.д. Передача такого имени функции
open
возвращает новый дескриптор файла, что в сущности является тем же самым, что и вызов
dup
для данного номера дескриптора.

98

На системах GNU/Linux

/dev/fd
является символической ссылкой на
/proc/self/fd
, но поскольку
/dev/fd
является общеизвестным, в своем коде следует использовать именно его — Примеч. автора.

Эти специальные файлы находят свое применение на уровне оболочки: Bash,

ksh88
(некоторые версии) и
ksh93
предоставляют возможность замещения процесса (process substitution), что позволяет создавать нелинейные конвейеры. На уровне оболочки для входного конвейера используется запись '
<(...)
', а для выходного конвейера запись '
>(...)
'. Например, предположим, вам нужно применить команду
diff
к выводу двух команд. Обычно вам пришлось бы использовать временные файлы:

command1 > /tmp/out.$$.1

command2 > /tmp/out.$$.2

diff /tmp/out.$$.1 /tmp/out.$$.2

rm /tmp/out.$$.1 /tmp/out.$$.2

С замещением процессов это выглядит следующим образом:

diff <(command1) <(command2)

Не надо никаких беспорядочных файлов для временного запоминания и удаления. Например, следующая команда показывает, что наш домашний каталог является ссылкой на другой каталог:

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

Третий. Том 2

INDIGO
2. Отпуск
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
Третий. Том 2

Неучтенный элемент. Том 3

NikL
3. Антимаг. Вне системы
Фантастика:
фэнтези
5.00
рейтинг книги
Неучтенный элемент. Том 3

Я еще не барон

Дрейк Сириус
1. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я еще не барон

Воронцов. Перезагрузка. Книга 4

Тарасов Ник
4. Воронцов. Перезагрузка
Фантастика:
попаданцы
альтернативная история
фэнтези
фантастика: прочее
6.00
рейтинг книги
Воронцов. Перезагрузка. Книга 4

Князь Андер Арес 3

Грехов Тимофей
3. Андер Арес
Фантастика:
рпг
аниме
фэнтези
5.00
рейтинг книги
Князь Андер Арес 3

Трое с площади Карронад

Крапивин Владислав Петрович
Детские:
детские приключения
9.10
рейтинг книги
Трое с площади Карронад

Первый среди равных. Книга II

Бор Жорж
2. Первый среди Равных
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Первый среди равных. Книга II

Газлайтер. Том 19

Володин Григорий Григорьевич
19. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 19

Зодчий. Книга II

Погуляй Юрий Александрович
2. Зодчий Империи
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Зодчий. Книга II

Лекарь Империи 6

Карелин Сергей Витальевич
6. Лекарь Империи
Фантастика:
городское фэнтези
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Лекарь Империи 6

На границе империй. Том 9. Часть 3

INDIGO
16. Фортуна дама переменчивая
Фантастика:
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 9. Часть 3

Гром Раскатного. Том 2

Володин Григорий Григорьевич
2. Штормовой Предел
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Гром Раскатного. Том 2

Старый, но крепкий 5

Крынов Макс
5. Культивация без насилия
Фантастика:
рпг
аниме
уся
фэнтези
5.00
рейтинг книги
Старый, но крепкий 5

Прапорщик. Назад в СССР. Книга 6

Гаусс Максим
6. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Прапорщик. Назад в СССР. Книга 6