Это "безопасно" поскольку не произойдет сбой, но если вы не продолжите звонить read, пока не получите EAGAIN (или ноль, что означает, что другой конец закрыл соединение), вы иногда будете ошибаться. предположения о доступности данных. Хуже всего то, что большую часть времени он будет выглядеть так, как будто он работает нормально.
Оповещение, инициируемое границей, а не уведомление, инициируемое уровнем, гарантирует, что вы получите только одно уведомление, если состояние готовности изменилось с момента последнего вызова epoll_wait, даже если остались данные, которые вы могли прочитать.
Уведомление о событии, инициируемое Edge, действительно иногда ведет себя странно или неинтуитивно в Linux, поэтому оно может делать что-то отличное от того, что вы ожидаете, и, например, дать вам еще одно уведомление, когда поступит больше данных (так что ваш код будет работать в любом случае), но это не то, что гарантируется.
У меня были подобные «сюрпризы» при использовании epoll с eventfd. Ожидается, что в режиме с запуском по фронту все потоки, которые уже заблокированы, пробуждаются (все в одно и то же время и ровно один раз), и все, вызывающие epoll_wait после события, блокируются до тех пор, пока событие не будет использовано и подается сигнал снова. На самом деле он пробуждает первый поток, вызвавший epoll_wait. И снова сюрприз, режим с запуском по уровню работает именно так, как вы хотели бы, за исключением того, что вы должны использовать событие, чтобы иметь возможность подготовить его снова, для чего нет правильного способа сделать это (поскольку вы должны сделать это ровно один раз или вы заблокируете read).
Таким образом, если вы не израсходуете все данные и позже дождетесь повторного уведомления, вам может повезти, и оно «все равно сработает», или вы можете ждать довольно долго, возможно, навсегда. Поэтому я рекомендую определенно продолжать чтение, пока не получите EAGAIN, это единственная по-настоящему надежная вещь, позволяющая избежать неожиданностей.
Обратите внимание, что вы можете морить голодом медленных отправителей, если будете продолжать наивно читать. Если у вас очень быстрый отправитель, и вы продолжаете читать на быстром отправителе, то вы никогда не увидите EAGAIN (по крайней мере, до тех пор, пока другой конец продолжает отправлять!), и вы полностью лишите других отправителей.
Это поэтому имеет смысл поместить все готовые дескрипторы в список и читать их циклически, удаляя их из списка, когда они возвращают EAGAIN.
person
Damon
schedule
14.01.2014