0Pricing
C++ Academy · Урок

Асинхронный IO с epoll и kqueue

Масштабируйте работу с множеством соединений с помощью epoll в Linux и kqueue в BSD или macOS.

«Асинхронный IO с epoll и kqueue» — бесплатный урок C++ Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C++ Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C++ Academy содержит 4 уроков всего.

Зачем нужен асинхронный ввод-вывод?

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

Linux: epoll

epoll — масштабируемый API событий в Linux. Добавьте файловые дескрипторы в экземпляр epoll и ожидайте событий от любого из них.

#include <sys/epoll.h>
int epfd = epoll_create1(0);
epoll_event ev{};
ev.events = EPOLLIN;
ev.data.fd = sock;
epoll_ctl(epfd, EPOLL_CTL_ADD, sock, &ev);

Ожидание событий

epoll_wait блокирует выполнение, пока не появятся события, а затем возвращает готовые дескрипторы.

epoll_event events[64];
int n = epoll_wait(epfd, events, 64, -1);
for (int i = 0; i < n; ++i) {
    int fd = events[i].data.fd;
    handle_io(fd);
}

Режимы срабатывания по фронту и по уровню

Есть два режима:

  • Срабатывание по уровню (по умолчанию) — epoll продолжает сообщать о событии, пока выполняется условие
  • Срабатывание по фронту (EPOLLET) — сообщает только об изменении состояния; каждый раз необходимо полностью вычитать данные из сокета

macOS и BSD: kqueue

kqueue — эквивалент epoll в BSD, также доступный в macOS. Концептуально они похожи, но используют разные API.

#include <sys/event.h>
int kq = kqueue();
struct kevent ev;
EV_SET(&ev, sock, EVFILT_READ, EV_ADD, 0, 0, nullptr);
kevent(kq, &ev, 1, nullptr, 0, nullptr);

Windows: IOCP

Windows использует порты завершения операций ввода-вывода (IOCP) — модель на основе завершения (уведомление после завершения операции), а не модель готовности, используемую epoll и kqueue.

Неблокирующие сокеты

Переведите сокеты в неблокирующий режим с помощью fcntl(fd, F_SETFL, O_NONBLOCK). Иначе чтение и запись могут заблокировать весь цикл обработки событий.

Шаблон цикла обработки событий

Цикл, работающий бесконечно:

  1. Ожидать готовых событий
  2. Для каждого события выполнять ввод-вывод, пока операция не заблокируется
  3. Повторять

Обработка множества клиентов

Один поток epoll может обрабатывать десятки тысяч одновременных соединений — это задача C10K. Современные системы способны работать с миллионами соединений.

Распространённые ошибки

Следите за следующими проблемами:

  • Забыли включить неблокирующий режим
  • Используете срабатывание по фронту, но не вычитываете сокет полностью
  • Не удаляете закрытые файловые дескрипторы из набора epoll
  • Допускаете утечки буферов для каждого соединения

Высокоуровневые обёртки

Ручная реализация цикла epoll чревата ошибками. Для промышленного кода используйте libuv, libevent или Boost.Asio — они скрывают различия платформ и предоставляют протестированные циклы ввода-вывода.

Асинхронный ввод-вывод и потоки

Асинхронный ввод-вывод лучше масштабируется, но его сложнее писать. Для серверов с несколькими тысячами соединений модель с отдельным потоком для каждого соединения проще. Выбирайте подход с учётом ожидаемой нагрузки.

Быстрая проверка

Чем отличаются режимы срабатывания по фронту и по уровню в epoll?

Итоги

Асинхронный ввод-вывод поддерживает огромное количество одновременных соединений, обрабатывая множество сокетов в одном потоке. В Linux используется epoll, в BSD и macOS — kqueue, а в Windows — IOCP. Переводите сокеты в неблокирующий режим. В промышленном коде используйте библиотеку (Asio, libuv, libevent), а не пишите цикл обработки событий вручную.

Часто задаваемые вопросы

Урок «Асинхронный IO с epoll и kqueue» бесплатный?

Да — полный текст урока «Асинхронный IO с epoll и kqueue» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C++ Academy, подпишись на CoddyKit PRO. Курс C++ Academy содержит 4 уроков всего.

Чему я научусь в уроке «Асинхронный IO с epoll и kqueue»?

Масштабируйте работу с множеством соединений с помощью epoll в Linux и kqueue в BSD или macOS. Ты практикуешь C++ Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать C++ Academy?

Предыдущий опыт не требуется. C++ Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.

Сколько времени занимает урок «Асинхронный IO с epoll и kqueue»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке C++ Academy?

Да. Каждый урок C++ Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. API сокетов BSD в C++
  2. Создание эхо-сервера TCP
  3. Асинхронный IO с epoll и kqueue
  4. Использование Boost Asio для современного асинхронного IO
← Назад к C++ Academy