Категории
Самые читаемые
PochitayKnigi » Компьютеры и Интернет » Интернет » Linux программирование в примерах - Роббинс Арнольд

Linux программирование в примерах - Роббинс Арнольд

Читать онлайн Linux программирование в примерах - Роббинс Арнольд

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 127 128 129 130 131 132 133 134 135 ... 253
Перейти на страницу:

9.4.3.5. Сводка fcntl()

Сводка для системного вызова fcntl() приведена в табл. 9.5.

Таблица 9.5. Сводка fcntl()

Значение cmd Значение arg Возвращает F_DUPFD Наименьший новый дескриптор Дублирует аргумент fd F_GETFD Получает флаги дескриптора файла (close-on-exec) F_SETFD Новое значение флага Устанавливает флаги дескриптора файла (close-on-exec) F_GETFL Получает флаги основного файла F_SETFL Новое значение флага Устанавливает флаги основного файла

Флаги создания, статуса и прав доступа файла копируются, когда дескриптор файла дублируется. Флаг close-on-exec не копируется.

9.5. Пример: двусторонние каналы в gawk

Двусторонний канал соединяет два процесса двунаправленным образом. Обычно, по крайней мере для одного из процессов, на канал с другим процессом настраиваются как стандартный ввод, так и стандартный вывод. Оболочка Корна (ksh) ввела двусторонние каналы на уровне языка, обозначив термином сопроцесса (coprocess):

<i>команды и аргументы движка базы данных</i> |&amp; /* Запустить сопроцесс в фоновом режиме */

print -p &quot;команда базы данных&quot; /* Записать в сопроцесс */

read -p db_response /* Прочесть из сопроцесса */

Здесь движок базы данных представляет любую серверную программу, которая может управляться интерфейсной частью, в данном случае, сценарием ksh. У движка базы данных стандартный ввод и стандартный вывод подсоединены к оболочке посредством двух отдельных односторонних каналов.[102] Это показано на рис. 9.7.

Рис. 9.7. Сопроцессы оболочки Корна

В обычном awk каналы к или от подпроцесса являются односторонними: нет способа послать данные в программу и прочесть посланные от нее в ответ данные — нужно использовать временный файл. GNU awk (gawk) заимствует обозначение '|&amp;' от ksh для расширения языка awk:

print &quot;<i>команда</i>&quot; |&amp; &quot;<i>движок базы данных</i>&quot; /* Запустить сопроцесс, записать в него */

&quot;<i>движок базы данных</i>&quot; |&amp; getline db_response /* Прочесть из сопроцесса */

gawk использует запись '|&amp;' также для сокетов TCP/IP и порталов BSD, которые не рассматриваются в данной книге. Следующий код из io.c в дистрибутиве gawk 3.1.3 является частью функции two_way_open(), которая устанавливает простой сопроцесс: она создает два канала, порождает новый процесс и осуществляет все манипуляции с дескриптором файла. Мы опустили ряд не относящихся к делу частей кода (эта функция занимает больше места, чем следовало бы):

1561 static int

1562 two_way_open(const char *str, struct redirect *rp)

1563 {

      ...

1827 /* случай 3: двусторонний канал с порожденным процессом */

1828 {

1829  int ptoc[2], сtop[2];

1830  int pid;

1831  int save_errno;

1835

1836  if (pipe(ptoc) &lt; 0)

1837   return FALSE; /* установлен errno, диагностика от вызывающего */

1838

1839  if (pipe(ctop) &lt; 0) {

1840   save_errno = errno;

1841   close(ptoc[0]);

1842   close(ptoc[1]);

1843   errno = save_errno;

1844   return FALSE;

1845  }

Первым шагом является создание двух каналов, ptoc является каналом «от родителя к потомку», а ctop — «от потомка к родителю». Во время чтения держите в уме, что индекс 0 является читаемым концом, а 1 — записываемым.

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

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

1906 if ((pid = fork()) &lt; 0) {

1907  save_errno = errno;

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

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

1910  errno = save_errno;

1 ... 127 128 129 130 131 132 133 134 135 ... 253
Перейти на страницу:
Тут вы можете бесплатно читать книгу Linux программирование в примерах - Роббинс Арнольд.
Комментарии