Выбирать и опрашивать системные вызовы. проблема многих событий записи

У меня есть установка с сервером/клиентом, имеющими много соединений друг с другом. Данные отправляются в больших объемах. Системные вызовы select или poll возвращают многие файловые дескрипторы как готовые к записи. Но по мере того, как я продолжаю записывать данные, в конце концов, с N-м файловым дескриптором я получаю EAGAIN с нулевым записанным байтом. И это продолжается по большей части.

Насколько я понимаю, это внутренний буфер ядра, который заполняется. Таким образом, остальные файловые дескрипторы не получают данных, отправляемых при пробуждении syscall.

Мой вопрос: все ли файловые дескрипторы получают сигнал справедливо? Я имею в виду, что из общего количества файловых дескрипторов первая группа получает сигнал и перемещается в хвост доступной для записи очереди. Если нет, то как побороть вышесказанное, как сделать так, чтобы всем сокетам, которым нужна передача данных, уделялось должное внимание?

И в результате вопрос, могу ли я пропустить цикл событий, если начнет появляться EAGAIN?

Я программирую на C, ссылки на код и пояснения приветствуются.

Я бы ожидал поведения FIFO и того, что вы хотите обработать любые файловые дескрипторы, готовые до повторения цикла событий.

Allan Wind 30.09.2022 23:43

@AllanWind Спасибо за предложение. Я добавил теги, специфичные для ОС.

user14063792468 30.09.2022 23:44

Linux не дает вам EAGAIN при заполнении справочной страницы (говорится, что это делают другие операционные системы Unix). Я ничего не знаю о FreeBSD.

Allan Wind 30.09.2022 23:45

@AllanWind Я не могу запустить Linux на данный момент. Глядя на справочные страницы в Интернете для Linux, я не нашел ничего более подходящего, кроме EAGAIN. Поэтому я разместил код ошибки для простоты чтения.

user14063792468 30.09.2022 23:53

Вы отметили свой вопрос linux, поэтому я упомянул об этом. Из select(2) «В некоторых других UNIX-системах select() может завершиться ошибкой EAGAIN, если системе не удается выделить внутренние ресурсы ядра, а не ENOMEM, как это делает Linux. POSIX указывает эту ошибку для poll(2), но не для select(). Переносимые программы могут захотеть проверить наличие EAGAIN и цикла, как и в случае с EINTR."

Allan Wind 01.10.2022 01:01
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Мой вопрос: все ли файловые дескрипторы получают сигнал справедливо?

И poll, и select вернут информацию о том, какие дескрипторы файлов в настоящее время доступны для чтения/записи на момент возврата вызова. Это «справедливо» в том смысле, что все они указаны одновременно. Вам нужно будет перебрать все дескрипторы и записать каждый из них, который доступен для записи. Вы можете предпочесть одни из них другим, если хотите, или сделать свою петлю более справедливой.

Когда вы write переходите к дескриптору, он возвращает EAGAIN или EWOULDBLOCK для любого неблокирующего и не имеющего буферного пространства. Каждый fd имеет свой собственный буфер, так что это, происходящее в одном fd, не имеет никакого отношения к каким-либо другим fd, и они все еще могут быть доступны для записи.

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

user14063792468 02.10.2022 22:22

Другие вопросы по теме