Читать «UNIX: взаимодействие процессов» онлайн - страница 41

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

Аргумент mode указывает битовую маску разрешений доступа к файлу, аналогично второму аргументу команды open. В табл. 2.3 приведены шесть констант, определенных в заголовке <sys/stat.h>. Эти константы могут использоваться для задания разрешений доступа и к FIFO.

Функция mkfifo действует как open, вызванная с аргументом O_CREAT | O_EXCL. Это означает, что создается новый канал FIFO или возвращается ошибка EEXIST, в случае если канал с заданным полным именем уже существует. Если не требуется создавать новый канал, вызывайте open вместо mkfifo. Для открытия существующего канала или создания нового в том случае, если его еще не существует, вызовите mkfifo, проверьте, не возвращена ли ошибка EEXIST, и если такое случится, вызовите функцию open.

Команда mkfifо также создает канал FIFO. Ею можно пользоваться в сценариях интерпретатора или из командной строки.

После создания канал FIFO должен быть открыт на чтение или запись с помощью либо функции open, либо одной из стандартных функций открытия файлов из библиотеки ввода-вывода (например, fopen). FIFO может быть открыт либо только на чтение, либо только на запись. Нельзя открывать канал на чтение и запись, поскольку именованные каналы могут быть только односторонними. 

При записи в программный канал или канал FIFO вызовом write данные всегда добавляются к уже имеющимся, а вызов read считывает данные, помещенные в программный канал или FIFO первыми. При вызове функции lseek для программного канала или FIFO будет возвращена ошибка ESPIPE.

Пример

Переделаем программу, приведенную в листинге 4.1, таким образом, чтобы использовать два канала FIFO вместо двух программных каналов. Функции client и server останутся прежними; отличия появятся только в функции main, новый текст которой приведен в листинге 4.6.

Листинг 4.6. Функция main приложения клиент-сервер, использующего две очереди

//pipe/mainfifo.c

1  #include "unpipc.h"

2  #define FIFO1 "/tmp/fifo.1"

3  #define FIFO2 "/tmp/fifo.2"

4  void client(int, int), server(int. int);

5  int

6  main(int argc, char **argv)

7  {

8   int readfd, writefd;

9   pid_t childpid;

10  /* создание двух FIFO, если существуют – OK */

11  if ((mkfifo(FIF01, FILE_MODE) < 0) && (errno != EEXIST))

12   err_sys("can't create %s", FIF01);

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

14   unlink(FIF01);

15   err_sys("can't create %s", FIF02);

16  }

17  if ((childpid = Fork()) == 0) { /* child */

18   readfd = Open(FIF01, O_RDONLY, 0);

19   writefd = Open(FIF02, O_WRONLY, 0);

20   server(readfd, writefd);

21   exit(0);

22  }

23  /* родительский процесс */

24  writefd = Open(FIF01, O_WRONLY, 0);

25  readfd = Open(FIF02, O_RDONLY, 0);

26  client(readfd, writefd);

27  waitpid(childpid, NULL, 0); /* ожидание завершения дочернего процесса */

28  Close(readfd):

29  Close(writefd);

30  Unlink(FIF01);

31  Unlink(FIF02);

32  exit(0);

33 }

Создание двух FIFO

10-16 В файловой системе в каталоге /tmp создается два канала. Если какой-либо из них уже существует — ничего страшного. Константа FILE_MODE определена в нашем заголовке unpiрс.h (листинг В.1) как