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

ЖАНРЫ

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

Троан Эрик В.

Шрифт:

Каждый системный вызов

struct epoll_event
сообщает программе полное состояние контролируемого файлового дескриптора. Элемент
events
может иметь установленные флаги
EPOLLIN
,
EPOLLOUT
или
EPOLLPRI
, а также два новых флага, которые описаны ниже.

EPOLLERR
С файлом связано ожидающее состояние ошибки; это случается, если ошибка происходит в сокете, когда приложение не считывает из него или не записывает в него.
EPOLLHUP
Файловый
дескриптор завис; в главе 10 дана информация о том, когда это обычно происходит.

На первый взгляд это все может показаться сложным, но на самом деле это очень похоже на работу

poll
. Вызов
epoll_create
— это то же, что и распределение массива
struct pollfd
, a
epoll_ctl
— это то же, что и инициализация элементов этого массива. Главный цикл, обрабатывающий файловые дескрипторы, использует
epoll_wait
вместо системного вызова
poll
, а
close
аналогичен освобождению памяти, занимаемой массивом
struct pollfd
. Эти параллели помогают переписывать с применением
epoll
программы мультиплексирования, которые изначально были реализованы с помощью
poll
или
select
.

Интерфейс

epoll
предлагает еще одну возможность, которую невозможно сравнить с
poll
или
select
. Поскольку дескриптор
epoll
в действительности является файловым дескриптором (вот почему его можно передавать
close
), имеется возможность контролировать дескриптор
epoll
как часть еще одного дескриптора
epoll
либо через
poll
или
select
. Дескриптор
epoll
будет готов к чтению из любого места, а вызов
epoll_wait
вернет события.

В окончательном решении проблемы мультиплексирования каналов, предложенном в данном разделе, используется

epoll
. Оно очень похоже на другие примеры, вот только определенная часть кода инициализации перемещена в новую функцию
addEvent
для предотвращения нежелательного удлинения программы.

 1: /* mpx-epoll.c */

 2:

 3: #include <fcntl.h>

 4: #include <stdio.h>

 5: #include <stdlib.h>

 6: #include <sys/epoll.h>

 7: #include <unistd.h>

 8:

 9: #include <sys/poll.h>

10:

11: void addEvent(int epfd, char * filename) {

12: int fd;

13: struct epoll_event event;

14:

15: if ((fd = open (filename, O_RDONLY | O_NONBLOCK)) < 0) {

16: perror("open");

17: exit(1);

18: }

19:

20: event.events = EPOLLIN;

21: event.data.fd = fd;

22:

23: if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event)) {

24: perror("epoll_ctl(ADD)");

25: exit(1);

26: }

27: }

28:

29: int main(void) {

30: char buf[4096];

31: int i, rc;

32: int epfd;

33: struct epoll_event events[2];

34: int num;

35: int numFds;

36:

37: epfd = epoll_create(2);

38: if (epfd < 0) {

39: perror("epoll_create");

40: return 1;

41: }

42:

43: /*
открыть оба канала и добавить их в набор epoll */

44: addEvent(epfd, "p1");

45: addEvent(epfd, "p2");

46:

47: /* продолжать, пока есть один или более файловых дескрипторов

48: для слежения */

49: numFds = 2;

50: while (numFds) {

51: if ((num = epoll_wait(epfd, events,

52: sizeof(events) / sizeof(* events),

53: -1)) <= 0) {

54: perror("epoll_wait");

55: return 1;

56: }

57:

58: for (i = 0; i < num; i++) {

59: /* events[i].data.fd готов для чтения */

60:

61: rc = read(events[i].data.fd, buf, sizeof(buf) - 1);

62: if (rc < 0) {

63: perror("read");

64: return 1;

65: } else if (!rc) {

66: /* этот канал закрыт, не пытаться

67: читать из него снова */

68: if (epoll_ctl(epfd, EPOLL_CTL_DEL,

69: events[i].data.fd, &events[i])) {

70: perror("epoll_ctl (DEL)");

71: return 1;

72: }

73:

74: close(events[i].data.fd);

75:

76: numFds--;

77: } else {

78: buf[rc] = '\0';

79: printf("чтение: %s", buf);

80:

81: }

82: }

83:

84: close(epfd);

85:

86: return 0;

87: }

13.1.6 Сравнение

poll
и
epoll

Методы

poll
и
epoll
существенно отличаются;
poll
хорошо стандартизован, но плохо масштабируется, в то время как
epoll
существует только в Linux, но очень хорошо масштабируется. Приложения, наблюдающие за небольшим количеством файловых дескрипторов и переносимости величин, должны использовать
poll
, но любому приложению, которому необходимо контролировать большое количество дескрипторов, лучше применять
epoll
, даже если ему нужно поддерживать
poll
для других платформ.

Поделиться с друзьями: