Как упоминалось в главе 11, неблокируемый файл можно определить с помощью системного вызова fcntl. Если медленный файл неблокируемый, read() сразу же возвращается. Если данные недоступны, она просто возвращает 0. Неблокируемый ввод- вывод предоставляет простое решение мультиплексирования, предотвращая блокирование файловых операций.

Показанная ниже модифицированная версия mpx-blocks пользуется преимуществом неблокируемого ввода-вывода для более гладкого переключения между p1 и p2.

 1: /* mpx-nonblock.c */

 2:

 3: #include <errno.h>

 4: #include <fcntl.h>

 5: #include <stdio.h>

 6: #include <unistd.h>

 7:

 8: int main(void) {

 9:  int fds[2];

10:  char buf[4096];

11:  int i;

12:  int fd;

13:

14:  /* открыть оба канала в неблокирующем режиме */

15:  if ((fds[0] = open('p1', O_RDONLY | O_NONBLOCK)) < 0) {

16:   perror('open p1');

17:   return 1;

18:  }

19:

20:  if ((fds[1] = open('p2', O_RDONLY | O_NONBLOCK)) < 0) {

21:   perror('open p2');

22:   return 1;

23:  }

24:

25:  fd = 0;

26:  while (1) {

27:   /* если данные доступны, прочитать и отобразить их */

28:   i = read(fds[fd], buf, sizeof (buf) - 1);

29:   if ((i < 0) && (errno ! = EAGAIN)) {

30:    perror('read');

31:    return 1;

32:   } else if (i > 0) {

33:    buf[i] = '';

34:    printf('чтение: %s', buf);

35:   }

36:

37:   /* читать из другого файлового дескриптора */

38:   fd = (fd + 1) % 2;

39:  }

40: }

Важное различие между mpx-nonblock и mpx-blocks состоит в том, что программа mpx-nonblock не закрывается, когда один из каналов, из которого она считывает, закрыт. Неблокируемый read() из канала без записывающих устройств возвращает 0 байт, из канала с таковыми, но без доступных данных read() возвращает EAGAIN.

Простое переключение неблокируемого ввода-вывода между дескрипторами файлов достается высокой ценой. Программа всегда опрашивает два файловых дескриптора для ввода — она никогда не блокируется. Постоянная работа программы приносит системе массу проблем, поскольку операционная система не может перевести процесс в режим ожидания (попробуйте запустить 10 копий mpx- nonblock в своей системе и посмотрите, как это скажется на ее производительности).

13.1.2. Мультиплексирование с помощью poll()

Для эффективного мультиплексирования Linux предоставляет системный вызов poll() , позволяющий процессу блокировать одновременно несколько файловых дескрипторов. Постоянно проверяя каждый файловый дескриптор, процесс создает отдельный системный вызов, определяющий, из каких файловых дескрипторов процесс будет читать, а на какие — записывать. Когда один или несколько таких файлов имеют данные, доступные для чтения, или могут принимать данные, записываемые в них, poll() завершается, и приложение может считывать и записывать данные в дескрипторах, не беспокоясь о блокировке. После обработки этих файлов процесс создает еще один вызов poll() , блокируемый до готовности файла. Ниже показано определение poll().

#include <sys/poll.h>

int poll(struct pollfd * fds, int numfds, int timeout);

Последние два параметра очень просты; numfds задает количество элементов в массиве, на который указывает первый параметр, a timeout определяет, насколько долго poll() должна ожидать события. Если в качестве тайм-аута задается 0, poll() никогда не входит в состояние тайм-аута.

Первый параметр, fds, описывает, какие файловые дескрипторы следует контролировать, и для каких типов ввода-вывода. Это указатель на массив структур struct pollfd.

struct pollfd {

 int fd;        /* файловый дескриптор */

 short events;  /* ожидаемые события ввода-вывода */

 short revents; /* происшедшие события ввода-вывода */

};

Первый элемент, fd, является контролируемым файловым дескриптором, а элемент events описывает, какие типы событий подлежат мониторингу. Последний представляет собой один или несколько перечисленных флагов, объединенных с помощью логического 'ИЛИ'.

POLLIN Нормальные данные доступны для считывания из файлового дескриптора.
POLLPRI Приоритетные (внешние) данные доступны для считывания.
Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

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

Отметить Добавить цитату