Чтение онлайн

на главную - закладки

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

32: } else if (i > 0) {

33: buf[i] = '\0';

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
Приоритетные (внешние) данные доступны для считывания.
POLLOUT
Файловый дескриптор может принимать записываемые на него данные.

Элемент

revents
структуры
struct pollfd
заполняется системным вызовом
poll
и отражает состояние файлового дескриптора
fd
. Это похоже на элемент
events
,
но вместо определения интересующих приложение событий ввода-вывода он определяет доступные такие типы. Например, если приложение контролирует канал как для чтения, так и для записи (
events
установлено в
POLLIN | POLLOUT
), после успешного вызова
poll
в
revents
устанавливается бит
POLLIN
, если канал готов для чтения, и бит
POLLOUT
, если в канале имеется пространство для записи дополнительных данных. Если верно и то, и другое, устанавливаются оба бита.

Существует несколько битов, которые ядро может установить в

revents
, но которые невозможно установить в
events
.

POLLERR
В дескрипторе файла имеется ожидающая ошибка; выполнение системного вызова на файловом дескрипторе приведет к установке
errno
в подходящий код.
POLLHUP
Файл был отключен; в него больше невозможно ничего записывать (хотя могут остаться данные для считывания). Это происходит в случае отключения терминала либо закрытия удаленного конца канала или сокета.
POLLNVAL
Файловый дескриптор недоступен (он не относится к открытому файлу).

Возвращаемое значение

poll
равно нулю в случае тайм-аута вызова, -1 в случае ошибки (например,
fds
— неверный указатель; ошибки в самих файлах вызывают установку
POLLERR
), или же положительное число, описывающее количество файлов с ненулевыми элементами revents.

В отличие от неэффективного метода мультиплексирования входных и выходных данных из каналов, используемого ранее,

poll
довольно легко решает ту же проблему. Применяя
poll
к файловым дескрипторам одновременно для обоих каналов, мы знаем, что когда
poll
возвращается, один из каналов готов для чтения либо закрыт. Мы проверяем элемент
revents
для обоих файловых дескрипторов, чтобы узнать, какие действия предпринять, и по завершении возвращаемся в вызов
poll
. Теперь большая часть времени тратится на блокирование вызова
poll
, а не на постоянную проверку файловых дескрипторов, использующих неблокируемый ввод-вывод, что значительно уменьшает нагрузку на систему. Ниже показан код
mpx-poll
.

 1: /* mpx-poll.с */

 2:

 3: #include <fcntl.h>

 4: #include <stdio.h>

 5: #include <sys/poll.h>

 6: #include <unistd.h>

 7:

 8: int main(void) {

 9: struct pollfdfds[2];

10: char buf [4096];

11: int i, rc;

12:

13: /* открыть оба канала */

14: if ( (fds[0].fd = open("p1", O_RDONLY | O_NONBLOCK)) < 0) {

15: perror("open p1");

16: return 1;

17: }

18:

19: if ((fds[1].fd = open("p2", O_RDONLY | O_NONBLOCK)) < 0) {

20: perror("open p2");

21: return 1;

22: }

23:

24: /* начать чтение из обоих файловых дескрипторов */

Поделиться:
Популярные книги

Отмороженный 8.0

Гарцевич Евгений Александрович
8. Отмороженный
Фантастика:
постапокалипсис
рпг
аниме
5.00
рейтинг книги
Отмороженный 8.0

Газлайтер. Том 14

Володин Григорий Григорьевич
14. История Телепата
Фантастика:
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Газлайтер. Том 14

Ермак. Телохранитель

Валериев Игорь
2. Ермак
Фантастика:
альтернативная история
7.00
рейтинг книги
Ермак. Телохранитель

Матабар IV

Клеванский Кирилл Сергеевич
4. Матабар
Фантастика:
фэнтези
5.00
рейтинг книги
Матабар IV

Сборник коротких эротических рассказов

Коллектив авторов
Любовные романы:
эро литература
love action
7.25
рейтинг книги
Сборник коротких эротических рассказов

Идеальный мир для Лекаря 19

Сапфир Олег
19. Лекарь
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 19

Дочь моего друга

Тоцка Тала
2. Айдаровы
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Дочь моего друга

Свет Черной Звезды

Звездная Елена
6. Катриона
Любовные романы:
любовно-фантастические романы
5.50
рейтинг книги
Свет Черной Звезды

Кодекс Крови. Книга IV

Борзых М.
4. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга IV

Идеальный мир для Лекаря 22

Сапфир Олег
22. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 22

Попаданка в академии драконов 4

Свадьбина Любовь
4. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.47
рейтинг книги
Попаданка в академии драконов 4

Сердце Дракона. Том 12

Клеванский Кирилл Сергеевич
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Сердце Дракона. Том 12

Лолита

Набоков Владимир Владимирович
Проза:
классическая проза
современная проза
8.05
рейтинг книги
Лолита

Сводный гад

Рам Янка
2. Самбисты
Любовные романы:
современные любовные романы
эро литература
5.00
рейтинг книги
Сводный гад