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

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

Жанры

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

Когда производитель вызывает на записывающем конце канала

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

Напротив, если потребитель закрывает читаемый конец,

write
на записываемом конце завершается неудачей. В частности, ядро посылает производителю сигнал «нарушенный канал», действием по умолчанию для которого является завершение процесса.

Нашей любимой аналогией для каналов является то, как муж и жена вместе моют и сушат тарелки. Один супруг моет тарелки, помещая чистые, но влажные тарелки в сушилку на раковине. Другой супруг вынимает тарелки из сушилки и вытирает их. Моющий тарелки является производителем, сушилка является каналом, а вытирающий является потребителем. [96]

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

96

Что они ели на обед, остается не указанным. — Примеч. автора.

Рис. 9.3. Синхронизация процессов канала

9.3.2. Очереди FIFO

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

Это может быть серьезным ограничением. Многие системные службы запускаются как демоны, отсоединенные долгоживущие процессы. Должен быть способ отправки данных таким процессам (и, возможно, получения данных от них). Файлы для этого не подходят; синхронизация трудна или невозможна, а каналы для выполнения задания не могут быть созданы, поскольку нет общих предков.

Для решения этой проблемы System III предложила идею о FIFO. FIFO, [97] или именованный канал, является файлом в файловой системе, который действует подобно каналу. Другими словами, один процесс открывает FIFO для записи, тогда как другой открывает его для чтения. Затем данные, записанные; в FIFO, читаются читателем. Данные буферируются ядром, а не хранятся на диске.

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

97

FIFO означает «first in, first out» — «первым вошел, первым вышел». Так работают каналы. — Примеч. автора.

Функция mkfifo создает файлы FIFO:

#include <sys/types.h> /* POSIX */

#include <sys/stat.h>

int mkfifo(const char *pathname, mode_t mode);

Аргумент

pathname
является именем создаваемого FIFO, a
mode
является данными ему правами доступа, аналогичными второму аргументу функции
creat
или третьему аргументу функции
open
(см. раздел 4.6 «Создание файлов»). Файлы FIFO удаляются, как любые другие, с помощью
remove
или
unlink
(см. раздел 5.1.5.1 «Удаление открытых файлов»).

Справочная страница GNU/Linux mkfifo(3) указывает, что FIFO должен быть открыт как для чтения, так и для записи в одно и то же время, до того, как может быть осуществлен ввод/вывод: «Открытие FIFO для чтения обычно блокирует до тех пор, пока какой-нибудь другой процесс не откроет тот же FIFO для записи, и наоборот». После открытия файла FIFO он действует подобно обычному каналу; т.е. это просто еще один дескриптор файла.

Команда

mkfifo
доставляет этот системный вызов на командный уровень. Это упрощает показ файла FIFO в действии:

$ mkfifo afifo /* Создание файла FIFO */

$ ls -l afifo

 /* Показать тип и права доступа, обратите внимание на 'p' впереди */

prw-r--r-- 1 arnold devel 0 Oct 23 15:49 afifo

$ cat < afifo & /* Запустить читателя в фоновом режиме */

[1] 22100

$ echo It was a Blustery Day > afifo /* Послать данные в FIFO */

$ It was a Blustery Day /* Приглашение оболочки, cat выводит данные */

 /* Нажмите ENTER, чтобы увидеть статус завершения задания */

[1]+ Done cat <afifo /* cat завершился */

9.4. Управление дескрипторами файлов

На данный момент части загадки почти полностью составлены,

fork
и
exec
создают процессы и запускают в них программы,
pipe
создает канал, который может использоваться для IPC. Чего до сих пор не хватает, так это способа помещения дескрипторов канала на место стандартных ввода и вывода для производителя и потребителя канала.

Системные вызовы

dup
и
dup2
, совместно с
close
дают вам возможность поместить (скопировать) открытый дескриптор файла на другой номер. Системный вызов
fcntl
дает вам возможность то же самое и управлять несколькими важными атрибутами открытых файлов.

9.4.1. Дублирование открытых файлов:

dup
и
dup2

Два системных вызова создают копию открытого дескриптора файла:

#include <unistd.h> /* POSIX */

int dup(int oldfd);

int dup2(int oldfd, int newfd);

Функции следующие:

int dup(int oldfd)

Возвращает наименьшее значение неиспользуемого дескриптора файла; это копия

oldfd
.
dup
возвращает неотрицательное целое в случае успеха и -1 при неудаче.

int dup2(int oldfd, int newfd)

Делает

newfd
копией
oldfd
; если
newfd
открыт, он сначала закрывается, как при использовании
close
.
dup2
возвращает новый дескриптор или -1, если была проблема. Помните рис. 9.1, в котором два процесса разделяли общие указатели на один и тот же элемент файла в таблице файлов ядра?
dup
и
dup2
создают ту же ситуацию внутри одного процесса. См. рис. 9.4.

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

Сирийский рубеж

Дорин Михаил
5. Рубеж
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Сирийский рубеж

Третий. Том 2

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

Студиозус

Шмаков Алексей Семенович
3. Светлая Тьма
Фантастика:
юмористическое фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Студиозус

Уязвимость

Рам Янка
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Уязвимость

Личный аптекарь императора. Том 4

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

Адвокат Империи 14

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

Наследник павшего дома. Том I

Вайс Александр
1. Расколотый мир
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник павшего дома. Том I

Паладин из прошлого тысячелетия

Еслер Андрей
1. Соприкосновение миров
Фантастика:
боевая фантастика
попаданцы
6.25
рейтинг книги
Паладин из прошлого тысячелетия

Наследник павшего дома. Том II

Вайс Александр
2. Расколотый мир [Вайс]
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник павшего дома. Том II

Барон диктует правила

Ренгач Евгений
4. Закон сильного
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Барон диктует правила

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

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

Черный Маг Императора 19

Герда Александр
19. Черный маг императора
Фантастика:
аниме
фэнтези
попаданцы
5.00
рейтинг книги
Черный Маг Императора 19

Контртеррор

Валериев Игорь
6. Ермак
Фантастика:
альтернативная история
5.00
рейтинг книги
Контртеррор

Ученик

Листратов Валерий
2. Ушедший Род
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Ученик