Вход/Регистрация
Разработка приложений в среде Linux. Второе издание
вернуться

Троан Эрик В.

Шрифт:

В определенной системе при не очень высоком значении

HIGH_FD
, равном 2, программа показала, что ядро за секунду может обрабатывать в четыре раза больше вызовов
poll
, чем вызовов
select
. При увеличении
HIGH_FD
до 1000 эффективность
poll
становится в 40 раз выше, чем у
select
.

13.1.5. Мультиплексирование с помощью

epoll

В версии 2.6 ядра Linux был предложен третий метод для мультиплексированного ввода-вывода по имени

epoll
. Будучи более сложным, чем
poll
или
select
,
epoll
ликвидирует узкие места, связанные с производительностью, которые характерны для обоих методов.

Оба системных вызова

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

При использовании

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

79

Фактически ядро устанавливает обратный вызов для каждого файла, а затем, когда происходит событие, активизирует обратный вызов. Этот механизм устраняет проблемы масштабируемости при очень большом количестве файловых дескрипторов, поскольку опрос не используется в каждой точке.

Преимущества в плане производительности

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

#include <sys/epoll.h>

int epoll_create (int numDescriptors);

Единственный параметр

numDescriptors
— это наилучшее предположение программы о том, на какое количество файловых дескрипторов будет ссылаться заново созданный дескриптор
epoll
. Это не жесткий предел, это просто подсказка ядру для более точной инициализации его внутренних структур.
epoll_create
возвращает дескриптор
epoll
, а когда программа заканчивает работу с дескриптором, его следует передать
close
, чтобы позволить ядру освободить память, используемую этим дескриптором.

Хотя дескриптор

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

#include <sys/epoll.h>

int epoll_ctl(int epfd, int op, int fd, struct epoll_event * event);

int epoll_wait(int epfd, struct epoll_event * events, int maxevents,

 int timeout);

Большинство этих параметров используют структуру

struct epoll_event
, которая определяется, как показано ниже.

#include <sys/epoll.h>

struct epoll_event {

 int events;

 union {

void * ptr;

int fd;

unsigned int u32;

unsigned long long u64;

 } data;

};

Эта структура обслуживает три цели: определяет, какие типы событий следует проверять, определяет типы произошедших событий и ассоциирует отдельный элемент данных с файловым дескриптором. Поле

events
предназначено для первых двух функций и является одной или несколькими перечисленными далее значениями, объединенными с помощью логического "ИЛИ" [80] .

80

EPOLLET
— это еще одно значение, которое может иметь
events
, переключающее
epoll
с запуска уровнем на запуск фронтом сигнала. Эта тема выходит за рамки настоящей книги, и
epoll
, запускаемую фронтом, следует применять только в особых случаях.

EPOLLIN
Определяет, что операция
read
не блокируется; данные или уже готовы, или их уже не осталось для считывания.
EPOLLOUT
Связанный файл готов для записи.
EPOLLPRI
Файл имеет внешние данные, готовые для чтения.

Второй элемент

struct epoll_event, data
, представляет собой объединение, содержащее целое число (для хранения файлового дескриптора), указатель, а также 32- и 64-битные целые числа [81] . Этот элемент данных хранится в
epoll
и возвращается в программу всякий раз, когда происходит событие подходящего типа. Элемент
data
— это единственный способ, с помощью которого программе нужно выяснить, какой файловый дескриптор необходимо обслужить; интерфейс
epoll
не передает файловый дескриптор программе, в отличие от
poll
и
select
(если
data
не содержит файловый дескриптор). Этот метод обеспечивает дополнительную гибкость приложениям, которые отслеживают файлы как нечто, более сложное, чем простые файловые дескрипторы.

81

Структура, показанная в тексте, предоставляет правильные размеры элементов на большинстве платформ, но они неправильны для машин, в которых

int
имеет 64 бита.

Системный вызов

epoll_ctl
добавляет файловые дескрипторы к набору, на который ссылается дескриптор
epfdepoll
, и удаляет их из него.

Второй параметр,

op
, описывает, каким образом следует модифицировать набор файловых дескрипторов, и является одним из перечисленных ниже.

EPOLL_CTL_ADD
Файловый дескриптор
fd
добавляется к набору файловых дескрипторов набором событий
events
. Если файловый дескриптор уже присутствует, он возвращает
EEXIST
. (Несколько потоков могут добавлять тот же файловый дескриптор к набору
epoll
более одного раза, но это действие ничего не меняет.)
EPOLL_CTL_DEL
Файловый дескриптор
fd
удаляется из контролируемого набора файловых дескрипторов. Параметр
events
должен указывать на
struct epoll_event
, но содержимое этой структуры игнорируется. (Это еще раз доказывает, что
events
должен быть допустимым указателем; он не может быть
NULL
.)
EPOLL_CTL_MOD
Системный вызов
struct epoll_event
для
fd
обновляется на основе информации, на которую указывает
events
. Это позволяет контролировать набор событий и обновлять элемент данных, ассоциируемый с файловым дескриптором, не создавая условий состязания.
  • Читать дальше
  • 1
  • ...
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

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