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

Мэтью Нейл

Шрифт:

Вызов

read
обычно будет задерживать выполнение процесса, т.е. он заставит процесс ждать до тех пор, пока не появятся данные. Если другой конец канала был закрыт, следовательно, нет ни одного процесса, имеющего канал для записи, и вызов
read
блокируется. Поскольку это не очень полезно, вызов
read
, пытающийся читать из канала, не открытого для записи, возвращает 0 вместо блокирования. Это позволит читающему процессу обнаружить канальный эквивалент метки "конец файла" и действовать соответствующим образом. Учтите, что это не то же самое, что чтение некорректного дескриптора файла, которое вызов read считает ошибкой и обозначает возвратом -1.

Если вы применяете канал с вызовом

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

Каналы, применяемые как стандартные ввод и вывод

Теперь, когда вы знаете, как заставить вызов

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

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

dup
, с которой вы встречались в главе 3. Существуют две тесно связанные версии функции
dup
, которые объявляются следующим образом:

#include <unistd.h>

int dup(int file_descriptor);

int dup2(int file_descriptor_one, int file_descriptor_two);

Назначение вызова

dup
— открыть новый дескриптор файла, немного похоже на то, как это делает вызов
open
. Разница в том, что файловый дескриптор, созданный
dup
, ссылается на тот же файл (или канал), что и существующий файловый дескриптор. В случае вызова
dup
новый файловый дескриптор всегда имеет самый маленький доступный номер, а в случае
dup2
— первый доступный дескриптор, больший чем значение параметра
file_descriptor_two
.

Примечание

Того же эффекта, что и применение вызовов

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

Итак, как же

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

Управление файловым дескриптором с помощью close и dup

Легче всего понять, что происходит, когда вы закрываете файловый дескриптор 0 и затем вызываете

dup
, если рассмотреть состояние первых четырех файловых дескрипторов, изменяющихся последовательно друг за другом (табл. 13.1).

Таблица 13.1

Номер файлового дескриптора Первоначально После закрытия файлового дескриптора 0 После вызова
dup
0 Стандартный ввод {closed} Файловый дескриптор канала
1 Стандартный вывод Стандартный вывод Стандартный вывод
2 Стандартный поток ошибок Стандартный поток ошибок Стандартный поток ошибок
3 Файловый дескриптор канала Файловый дескриптор канала Файловый дескриптор канала
  • Читать дальше
  • 1
  • ...
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • ...

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

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

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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