Читать «UNIX: взаимодействие процессов» онлайн - страница 43
Уильям Ричард Стивенс
Листинг 4.7. Функция main независимого сервера
//pipe/server_main.c
1 #include "fifo.h"
2 void server(int, int);
3 int
4 main(int argc, char **argv)
5 {
6 int readfd, writefd;
7 /* создание двух FIFO. OK, если они существуют */
8 if ((mkfifo(FIF01, FILE_MODE) < 0) && (errno != EEXIST))
9 err_sys("can't create %s", FIF01);
10 if ((mkfifo(FIF02, FILE MODE) < 0) && (errno != EEXIST)) {
11 unlink(FIF01);
12 err_sys("can't create %s", FIF02);
13 }
14 readfd = Open(FIF01, O_RDONLY, 0);
15 writefd = Open(FIFO2, O_WRONLY, 0);
16 server(readfd, writefd);
17 exit(0);
18 }
Листинг 4.8. Заголовочный файл fifo.h, используемый и клиентом, и сервером
//pipe/fifo.h
1 #include "unpipc.h"
2 #define FIFO1 "/tmp/fifo.1"
3 #define FIFO2 "/tmp/fifo.2"
Листинг 4.9. Функция main независимого клиента
//pipe/client_main.c
1 #include "fifo.h"
2 void client(int, int);
3 int
4 main(int argc, char **argv)
5 {
6 int readfd, writefd;
7 writefd = Open(FIFO1, O_WRONLY, 0);
8 readfd = Open(FIFO2, O_RDONLY, 0);
9 client(readfd, writefd);
10 Close(readfd);
11 Close(writefd);
12 Unlink(FIFO1);
13 UnLink(FIFO2);
14 exit(0);
15 }
ПРИМЕЧАНИЕ
Для программных каналов и каналов FIFO ядро ведет подсчет числа открытых дескрипторов, относящихся к ним, поэтому безразлично, кто именно вызовет unlink — клиент или сервер. Хотя эта функция и удаляет файл из файловой системы, она не влияет на открытые в момент ее выполнения дескрипторы. Однако для других форм IPC, таких как очереди сообщений стандарта System V, счетчик отсутствует, и если сервер удалит очередь после записи в нее последнего сообщения, она может быть удалена еще до того, как клиент это сообщение считает.
Для запуска клиента и сервера запустите сервер в фоновом режиме:
% server_fifo &
а затем запустите клиент. Можно было сделать и по-другому: запускать только программу-клиент, которая запускала бы сервер с помощью fork и exec. Клиент мог бы передавать серверу имена FIFO в качестве аргументов командной строки в команде exec, вместо того чтобы обе программы считывали их из заголовка. Но в этом случае сервер являлся бы дочерним процессом и проще было бы обойтись программным каналом.
4.7. Некоторые свойства именованных и неименованных каналов
Некоторые свойства именованных и неименованных каналов, относящиеся к их открытию, а также чтению и записи данных, заслуживают более пристального внимания. Прежде всего можно сделать дескриптор неблокируемым двумя способами.
1. При вызове open указать флаг O_NONBLOCK. Например, первый вызов open в листинге 4.9 мог бы выглядеть так:
writefd = Open(FIFO1, O_WRONLY | O_NONBLOCK, 0);
2. Если дескриптор уже открыт, можно использовать fcntl для включения флага O_NONBLOCK. Этот прием нужно применять для программных каналов, поскольку для них не вызывается функция open и нет возможности указать флаг O_NONBLOCK при ее вызове. Используя fcntl, мы сначала получаем текущий статус файла с помощью F_GETFL, затем добавляем к нему с помощью побитового логического сложения (OR) флаг O_NONBLOCK и записываем новый статус с помощью команды F_SETFL: