LINUX.ORG.RU

non-blocking splice + EPOLLET

 


0

3

Допустим, я хочу странного: использовать edge-triggered epoll (всегда мечтал, но руки все не доходили) + splice для работы с диском (отправка/получение файлов). При этом splice между (pipe => disk) и (net => pipe) происходят в отдельных тредах (в linux же не могут завести человеческое дисковое aio).

Проблема в том, что когда splice возвращает EAGAIN как-то очень нетривиально догадаться, кто виноват. Если использовать level-triggered IO, все просто: мониторим pipe и source/destination socket на готовность к чтению/записи и пишем/читаем. Получили EAGAIN — не паримся и уходим в epoll, позже видно будет, кто виноват.

Если использовать ioctl, чтобы понять, не переполнился ли пайп, можно наступить на race (splice file => pipe и pipe => socket происходят в разных потоках). Если узнать максимальный размер буфера pipe, также пойдут race, потому как операции «атомарно сделать splice и изменить userspace счетчик» не завезли. Можно обмазаться mutex'ами, но это убьет производительность (splice сможет делать только один поток).

С level-triggered все просто: получил событие, позвал splice и если наткнулся на EAGAIN, значит виновата «другая сторона», т. к. файловый дескриптор готов к чтению записи — гарантировано epoll'ом. Но level-triggered делают все, и в нем время от времени придется делать EPOLL_CTL_DEL. В edge-triggered не нужно в принципе изменять набор дескрипторов, но splice нужно проводить до победного EAGAIN, а там уже фиг поймешь, кто виноват.

Может есть какой-то красивый трюк, о котором никто не пишет?

P. S. Любители nginx и прочих готовых «быстрых веб-серверов» идут лесом — у меня душа странного требует.

splice file => pipe и pipe => socket

Если оба потока работают с одним pipe'ом, то зачем такое может быть нужно и чем это лучше sendfile()?

mky ★★★★★
()
Ответ на: комментарий от mky

Если оба потока работают с одним pipe'ом, то зачем такое может быть нужно

Чтобы прочая сетевая активность не залипала на несколько секунд, когда диски сильно нагружаются.

чем это лучше sendfile()?

Тем, что sendfile непригоден для последущей обработки, а со splice ты можешь одинаково эффективно обслуживать как обычный HTTP, так и HTTPS.

kawaii_neko ★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.