[1]+ Done   ./fifo2 O_RDONLY O_NONBLOCK

Эти два примера — вероятно, самые распространенные комбинации режимов open. Не стесняйтесь использовать программу-пример для экспериментов с другими возможными комбинациями.

Чтение из каналов FIFO и запись в них

Применение режима O_NONBLOCK влияет на поведение вызовов read и write в каналах FIFO.

Вызов read, применяемый для чтения из пустого блокирующего FIFO (открытого без флага O_NONBLOCK), будет ждать до тех пор, пока не появятся данные, которые можно прочесть. Вызов read, применяемый в неблокирующем FIFO, напротив, при отсутствии данных вернет 0 байтов.

Вызов write для записи в полностью блокирующий канал FIFO будет ждать до тех пор, пока данные не смогут быть записаны. Вызов write, применяемый к FIFO, который не может принять все байты, предназначенные для записи, либо:

□ будет аварийно завершен, если был запрос на запись PIPE_BUF байтов или меньше и данные не могут быть записаны;

□ запишет часть данных, если был запрос на запись более чем PIPE_BUF байтов, и вернет количество реально записанных байтов, которое может быть и 0.

Размер FIFO — очень важная характеристика. Существует накладываемый системой предел объема данных, которые могут быть в FIFO в любой момент времени. Он задается директивой #define PIPE_BUF, обычно находящейся в файле limits.h. В ОС Linux и многих других UNIX-подобных системах он обычно равен 4096 байт, но в некоторых системах может быть и 512 байт. Система гарантирует, что операции записи PIPE_BUF или меньшего количества байтов в канал FIFO, который был открыт O_WRONLY (т.е. блокирующий), запишут или все байты, или ни одного.

Несмотря на то, что этот предел не слишком важен в простом случае с одним записывающим каналом FIFO и одним читающим FIFO, очень распространено использование одного канала FIFO, позволяющего разным программам отправлять запросы к этому единственному каналу FIFO. Если несколько разных программ попытаются писать в FIFO в одно и то же время, жизненно важно, чтобы блоки данных из разных программ не перемежались друг с другом, т. е. каждая операция write должна быть "атомарной". Как это сделать?

Если вы ручаетесь, что все ваши запросы write адресованы блокирующему каналу FIFO и их размер меньше PIPE_BUF байтов, система гарантирует, что данные никогда не будут разделены. Вообще это неплохая идея — ограничить объем данных, передаваемых через FIFO блоком в PIPE_BUF байтов, если вы не используете единственный пишущий и единственный читающий процессы.

Выполните упражнение 13.12.

Упражнение 13.12. Связь процессов с помощью каналов FIFO

Для того чтобы увидеть, как несвязанные процессы могут общаться с помощью именованных каналов, вам понадобятся две отдельные программы fifo3.c и fifo4.c.

1. Первая программа — поставщик. Она создает канал, если требуется, и затем записывает в него данные как можно быстрее.

Примечание

Поскольку пример иллюстративный, нас не интересуют конкретные данные, и мы не беспокоимся об инициализации буфера, В обоих листингах затененные строки содержат изменения, внесенные в программу fifo2.c помимо удаления кода со всеми аргументами командной строки.

#include

#include

#include

#include

#include

#include

#include

#include

#define FIFO_NAME "/tmp/my_fifo"

#define BUFFER_SIZE PIPE_BUF

#define TEN_MEG (1024 * 1024 * 10)

int main() {

 int pipe_fd;

 int res;

 int open_mode = O_WRONLY;

 int bytes_sent = 0;

 char buffer[BUFFER_SIZE + 1];

 if (access(FIFO_NAME, F_OK) == -1) {

  res = mkfifo(FIFO_NAME, 0777);

  if (res != 0) {

   fprintf(stderr, "Could not create fifo %s\n", FIFO_NAME);

   exit(EXIT_FAILURE);

  }

 }

 printf("Process %d opening FIFO O_WRONLY\n", getpid());

 pipe_fd = open(FIFO_NAME, open_name);

 printf("Process %d result %d\n", getpid(), pipe_fd);

 if (pipe_fd != -1) {

  while (bytes_sent < TEN_MEG) {

   res = write(pipe_fd, buffer, BUFFER_SIZE);

   if (res == -1) {

    fprintf(stderr, "Write error on pipe\n);

    exit(EXIT_FAILURE);

   }

   bytes_sent += res;

  }

Перейти на страницу:

Похожие книги