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

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

Шрифт:

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)

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

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

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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