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

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

Жанры

UNIX: взаимодействие процессов

Стивенс Уильям Ричард

Шрифт:

10 /* создание FIFO с включением в его имя PID */

11 pid = getpid;

12 snprintf(fifoname, sizeof(fifoname), "/tmp/fifo,%ld", (long) pid):

13 if ((mkfifo(fifoname, FILE_MODE) < 0) && (errno != EEXIST))

14 err_sys("can't create %s", fifoname);

15 /* инициализация буфера PID и пробелом */

16 snprintf(buff, sizeof(buff), "%ld ", (long) pid);

17 len = strlen(buff);

18 ptr = buff + len;

19 /* считывание полного имени */

20 Fgets(ptr, MAXLINE – len, stdin);

21 len = strlen(buff); /* fgets гарантирует завершающий 0 */

22 /* открытие FIFO сервера и запись в него полного имени и PID */

23 writefifo = Open(SERV_FIFO, O_WRONLY, 0);

24 Write(writefifo, buff, len);

25 /* открытие созданного FIFO; блокирование до открытия его сервером */

26 readfifo = Open(fifoname, O_RDONLY; 0);

27 /* считывание из канала IPC, запись в stdout */

28 while ((n = Read(readfifo, buff, MAXLINE)) > 0)

29 Write(STDOUT_FILENO, buff, n);

30 Close(readfifo);

31 Unlink(fifoname);

32 exit(0);

33 }

Создание канала

10-14 Идентификатор процесса клиента содержится в имени создаваемого им канала.

Формирование строки запроса

15-21 Запрос клиента состоит из его идентификатора процесса, одного пробела, полного имени запрашиваемого им файла и символа перевода строки. Строка запроса формируется в массиве buff, причем имя файла считывается из стандартного потока ввода.

Открытие канала сервера и отправка запроса

22-24 Клиент открывает канал сервера и записывает в него строку запроса. Если клиент окажется первым с момента запуска сервера, вызов open разблокирует сервер, заблокированный после сделанного им вызова open (с флагом O_RDONLY).

Прием содержимого файла или сообщения об ошибке от сервера

25-31 Ответ сервера считывается из канала и записывается в стандартный поток вывода, после чего канал клиента закрывается и* удаляется.

Сервер может быть запущен в одном из окон, а клиент — в другом, и программа будет работать так, как мы и рассчитывали. Ниже мы приводим только текст, выводимый клиентом:

solaris % mainclient /etc/shadow файл, который нам нельзя читать

/etc/shadow: can't open. Permission denied

solaris % mainclient /etc/inet/ntp.conf файл из двух строк

multicastclient 224.0.1.1

driftfile /etc/inet/ntp.drift
 

Мы можем также связаться с сервером из интерпретатора команд, поскольку каналы FIFO обладают именами в файловой системе.

solaris % Pid=$$

solaris % mkfifo /tmp/fifo.$Pid

solaris % echo "$Pid /etc/inet/ntp.conf" > /tmp/fifo.serv

solaris % cat < /tmp/fifo.$Pid

multicastclient 224.0.1.1

driftfile /etc/inet/ntp.drift

solaris % rm /tmp/fifo.$Pid

Мы отсылаем серверу идентификатор процесса текущей копии интерпретатора и полное имя файла одной командой интерпретатора (echo) и считываем из канала сервера результат с помощью другой команды (cat). Между выполнением этих двух команд может пройти произвольный промежуток времени. Таким образом, сервер помещает содержимое файла в канал, а клиент затем запускает команду cat, чтобы считать оттуда данные. Может показаться, что данные каким-то образом хранятся в канале, хотя он не открыт ни одним процессом. На самом деле все не так. После закрытия пpoгрaммнoгo канала или FIFO последним процессом с помощью команды close все данные, в нем находящиеся, теряются. В нашем примере сервер, считав строку запроса от клиента, блокируется при попытке открыть канал клиента, потому что клиент (наша копия интерпретатора) еще не открыл его на чтение (вспомним табл. 4.1). Только после вызова cat некоторое время спустя канал будет открыт на чтение, и тогда сервер разблокируется. Кстати, таким образом осуществляется атака типа «отказ в обслуживании» (denial-of-service attack), которую мы обсудим в следующем разделе.

Использование интерпретатора позволяет провести простейшую проверку способности сервера обрабатывать ошибки. Мы можем отправить серверу строку без идeнтификaтopa процесса или отослать ему такой идентификатор, которому не соответствует никакой канал FIFO в каталоге /tmp. Например, если мы запустим сервер и введем нижеследующие строки:

solaris % cat > /tmp/fifo.serv /no/process/id

999999 /invalid/process/id

то сервер выдаст текст:

solaris % server

bogus request: /no/process/id

cannot open: /tmp/fifo.999999

Атомарность записи в FIFO

Наша простейшая пара клиент-сервер позволяет наглядно показать важность наличия свойства атомарности записи в пpoгрaммныe каналы и FIFO. Предположим, что два клиента посылают серверу запрос приблизительно в один и тот же момент. Первый клиент отправляет следующую строку:

1234 /etc/inet/ntp.conf

второй:

9876 /etc/passwd

Предполагая, что каждый клиент помещает данные в FIFO за один вызов write и кaждая строка имеет размер, не превышающий величины PIPE_BUF (что чаще всего заведомо выполняется, поскольку PIPE_BUF обычно лежит в диапазоне 1024-5120, а длина полного имени обычно oгрaничeнa 1024 байт), мы можем гарантировать, что в FIFO данные будут иметь следующий вид:

1234 /etc/inet/ntp.conf

9876 /etc/passwd

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

Зеркало силы

Кас Маркус
3. Артефактор
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Зеркало силы

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

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

Зауряд-врач

Дроздов Анатолий Федорович
1. Зауряд-врач
Фантастика:
альтернативная история
8.64
рейтинг книги
Зауряд-врач

Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Ву Тим
Деловая литература:
о бизнесе популярно
5.00
рейтинг книги
Главный рубильник. Расцвет и гибель информационных империй от радио до интернета

Город костей

Уэллс Марта
Фантастика:
научная фантастика
6.25
рейтинг книги
Город костей

Гром с севера

Мазуров Дмитрий
8. Громовая поступь
Фантастика:
фэнтези
рпг
5.00
рейтинг книги
Гром с севера

Наследник

Шимохин Дмитрий
1. Старицкий
Приключения:
исторические приключения
5.00
рейтинг книги
Наследник

Отмороженный

Гарцевич Евгений Александрович
1. Отмороженный
Фантастика:
боевая фантастика
рпг
5.00
рейтинг книги
Отмороженный

Я снова граф. Книга XI

Дрейк Сириус
11. Дорогой барон!
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Я снова граф. Книга XI

Солдат Империи

Земляной Андрей Борисович
1. Страж
Фантастика:
попаданцы
альтернативная история
6.67
рейтинг книги
Солдат Империи

Бастард

Осадчук Алексей Витальевич
1. Последняя жизнь
Фантастика:
фэнтези
героическая фантастика
попаданцы
5.86
рейтинг книги
Бастард

Ведун

Сухов Александр Евгеньевич
1. Второй шанс
Фантастика:
фэнтези
боевая фантастика
альтернативная история
5.00
рейтинг книги
Ведун

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

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

Дракон

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