logo
Операционные системы

Именованные каналы

Файловая система ОС Unix поддерживает некоторую совокупность файлов различных типов. Файловая система рассматривает каталоги как файлы специального типа каталог, обычные файлы, с которым мы имеем дело в нашей повседневной жизни, — как регулярные файлы, устройства, с которыми работает система, — как специальные файлы устройств. Точно так же файловая система ОС Unix поддерживает специальные файлы, которые называются FIFO-файлами (или именованными каналами). Файлы этого типа очень схожи с обыкновенными файлами (в них можно писать и из них можно читать информацию), за исключением того факта, что они организованы по стратегии FIFO (т.е. невозможны операции, связанные с перемещением файлового указателя).

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

Для создания файлов FIFO в различных реализациях используются разные системные вызовы, одним из которых может являться mkfifo()1.

int mkfifo(char *pathname, mode_t mode);

Первым параметром является имя создаваемого файла, а второй параметр отвечает за флаги владения, права доступа и т.п.

После создания именованного канала любой процесс может установить с ним связь посредством системного вызова open(). При этом действуют следующие правила:

Правила работы с именованными каналами, в частности, особенности операций чтения-записи, полностью аналогичны неименованным каналам.

Пример. «Клиент-сервер». В нижеприведенном примере один из процессов является сервером, предоставляющим некоторую услугу, другой же процесс, который хочет воспользоваться этой услугой, является клиентом. Клиент посылает серверу запросы на предоставление услуги, а сервер отвечает на эти запросы.

/* процесс-сервер */

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/file.h>

int main(int argc, char **argv)

{

int fd;

int pid;

mkfifo("fifo", FILE_MODE | 0666);

fd = open("fifo", O_RDONLY | O_NONBLOCK);

while(read(fd, &pid, sizeof(int)) == -1);

printf("Server %d got message from %d !\n", getpid(), pid);

close(fd);

unlink("fifo");

}

/* процесс-клиент */

#include <stdio.h>

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/file.h>

int main(int argc, char **argv)

{

int fd;

int pid = getpid();

fd = open("fifo", O_RDWR);

write(fd, &pid, sizeof(int));

close(fd);

}

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

Клиентский процесс открывает FIFO-файл в режиме чтения-записи, пишет в канал свой идентификатор процесса, а затем закрывает файловый дескриптор, ассоциированный с данным FIFO-файлом.