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

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

Жанры

Linux программирование в примерах
Шрифт:

Строки 1836–1837 создают первый канал,

ptoc
. Строки 1839–1845 создают второй канал, закрывая при неудачном создании и первый. Это важно. Небрежность в закрытии открытых, но не используемых каналов ведет к утечкам дескрипторов файлов. Как и память, дескрипторы файлов являются конечным ресурсом, и когда они иссякают, то теряются. [103] То же верно и для открытых файлов: убедитесь, что ваш обрабатывающий ошибки код всегда закрывает все открытые файлы и каналы, которые не нужны, когда происходит ошибка.

103

Очевидно, вы можете их закрыть. Но если вы не знаете, что они открыты, они теряются с таким же успехом, как и память через утечку памяти — Примеч. автора.

save_errno
сохраняет значения
errno
, установленные
pipe
, на тот редкий случай, когда
close
может завершиться неудачей (строка 1840). Затем
errno
восстанавливается в строке 1843.

1906 if ((pid = fork) < 0) {

1907 save_errno = errno;

1908 close(ptoc[0]); close(ptoc[1]);

1909 close(ctop[0]); close(ctop[1]);

1910 errno = save_errno;

1911 return FALSE;

1912 }

Строки 1906–1912 порождают процесс, на этот раз закрывая оба канала, если

fork
потерпит неудачу. Здесь также первоначальное значение
errno
сохраняется и восстанавливается для последующего использования при диагностике.

1914 if (pid == 0) { /* порожденный процесс */

1915 if (close(1) == -1)

1916 fatal(_("close of stdout in child failed (%s)"),

1917 strerror(errno));

1918 if (dup(ctop[1]) != 1)

1919 fatal(_{"moving pipe to stdout in child failed (dup: %s)"), strerror(errno));

1920 if (close(0) == -1)

1921 fatal(_("close of stdin in child failed (%s)"),

1922 strerror(errno));

1923 if (dup(ptoc[0]) != 0)

1924 fatal(_("moving pipe to stdin in child failed (dup: %s)"), strerror(errno));

1925 if (close(ptoc[0]) == -1 || close(ptoc[1]) == -1

1926 || close(ctop[0]) == -1 || close(ctop[1]) == -1)

1927 fatal(_("close of pipe failed (%s)"), strerror(errno));

1928 /* stderr HE дублируется в stdout потомка */

1929 execl("/bin/sh", "sh", "-c", str, NULL);

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

1931 }

Строки 1914–1931 обрабатывают код потомка, с соответствующей проверкой ошибок и сообщениями на каждом шагу. Строка 1915 закрывает стандартный вывод. Строка 1918 копирует записываемый конец канала от потомка к родителю на 1. Строка 1920 закрывает стандартный ввод, а строка 1923 копирует читаемый конец канала от родителя к потомку на 0. Если это все работает, стандартные ввод и вывод теперь на месте и подключены к родителю.

Строки 1925–1926 закрывают все четыре первоначальные дескрипторы файлов каналов, поскольку они больше не нужны. Строка 1928 напоминает нам, что стандартная ошибка остается на месте. Это лучшее решение, поскольку пользователь увидит ошибки от сопроцесса. Программа

awk
, которая должна перехватить стандартную ошибку, может использовать в команде обозначение '
2>&1
' для перенаправления стандартной ошибки сопроцесса или записи в отдельный файл.

Наконец, строки 1929–1930 пытаются запустить для оболочки

execl
и соответственно выходят, если это не удается.

1934 /* родитель */

1935 rp->pid = pid;

1936 rp->iop = iop_alloc(ctop[0], str, NULL);

1937 if (rp->iop == NULL) {

1938 (void)close(ctop[0]);

1939 (void)close(ctop[1]);

1940 (void)close(ptoc[0]);

1941 (void)close(ptoc[1]);

1942 (void)kill(pid, SIGKILL); /* overkill? (pardon pun) */

1943

1944 return FALSE;

1945 }

Первым шагом родителя является настройка входного конца от сопроцесса. Указатель

rp
указывает на
struct redirect
, которая содержит поле для сохранения PID порожденного процесса,
FILE*
для вывода и указатель
IOBUF*
с именем
iop
.
IOBUF
является внутренней структурой данных
gawk
для осуществления ввода. Она, в свою очередь, хранит копию нижележащего дескриптора файла.

Строка 1935 сохраняет значение ID процесса. Строка 1936 выделяет память для новой

IOBUF
для данных дескриптора файла и командной строки. Третий аргумент здесь равен
NULL
: он позволяет при необходимости использовать предварительно выделенный
IOBUF
.

Если выделение памяти потерпело неудачу, строки 1937–1942 производят очистку, закрывая каналы и посылая сигнал «kill» порожденным процессам, чтобы заставить их завершить работу. (Функция

kill
описана в разделе 10.6.7 «Отправка сигналов
kill
и
killpg
».)

1946 rp->fp = fdopen(ptoc[1], "w");

1947 if (rp->fp == NULL) {

1948 iop_close(rp->iop);

1949 rp->iop = NULL;

1950 (void)close(ctop[0]);

1951 (void)close(ctop[1]);

1952 (void)close(ptoc[0]);

1953 (void)close(ptoc[1]);

1954 (void)kill(pid, SIGKILL); /* избыточно? (пардон, каламбур)
[104]
*/

104

Игра слов kill-overkill (избыточно — overkill) — Примеч. перев.

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

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

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

Я С СССР! Том 5

Вязовский Алексей
5. Я спас СССР
Фантастика:
альтернативная история
6.22
рейтинг книги
Я С СССР! Том 5

Дракон

Бубела Олег Николаевич
5. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.31
рейтинг книги
Дракон

Самые знаменитые произведения писателя в одном томе

Брэдбери Рэй Дуглас
Фантастика:
фантастика: прочее
4.00
рейтинг книги
Самые знаменитые произведения писателя в одном томе

Звездная Кровь. Экзарх III

Рокотов Алексей
3. Экзарх
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Экзарх III

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

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

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

Я до сих пор князь. Книга XXII

Дрейк Сириус
22. Дорогой барон!
Фантастика:
юмористическое фэнтези
аниме
попаданцы
5.00
рейтинг книги
Я до сих пор князь. Книга XXII

Некромант

Щепетнов Евгений Владимирович
4. Петр Синельников
Фантастика:
боевая фантастика
6.20
рейтинг книги
Некромант

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

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

Убивать чтобы жить 7

Бор Жорж
7. УЧЖ
Фантастика:
героическая фантастика
космическая фантастика
рпг
5.00
рейтинг книги
Убивать чтобы жить 7

Хозяин теней 2

Демина Карина
2. Громов
Фантастика:
аниме
попаданцы
фэнтези
7.00
рейтинг книги
Хозяин теней 2

Портрет дьявола: Собрание мистических рассказов

Скотт Вальтер
Проза:
классическая проза
8.09
рейтинг книги
Портрет дьявола: Собрание мистических рассказов

Наследник для дона мафии

Тоцка Тала
2. Наследники мафии
Любовные романы:
остросюжетные любовные романы
эро литература
5.00
рейтинг книги
Наследник для дона мафии