Подтвердить что ты не робот

Несколько потоков, выполняющих опрос() или select() для одного сокета или канала

Что говорят POSIX и другие стандарты о ситуации, когда несколько потоков выполняют вызовы poll() или select() для одного дескриптора или дескриптора в одно и то же время?

Если какие-либо данные поступают, просыпается только один из ожидающих потоков или все просчитываемые потоки ожидания просчитываются?

4b9b3361

Ответ 1

Интересный вопрос... Я прочитал текущий POSIX и не нашел конкретного ответа, т.е. никакой спецификации о параллельных вызовах. Поэтому я объясню, почему я считаю, что стандарт означает, что все проснется.

Соответствующая часть текст для select/pselect:

После успешного завершения функция pselect() или select() должна изменить объекты на которые указывают аргументы readfds, writefds и errorfds, чтобы указать, какой файл дескрипторы готовы к чтению, готовы к записи или к ожиданию ошибки, соответственно, [...]

и позже

Дескриптор считается считанным готовым для чтения, когда вызов функции ввода с Очистка O_NONBLOCK не блокирует, будет ли функция передавать данные успешно. (Функция может возвращать данные, индикацию конца файла или ошибку кроме одного, указывающего, что он заблокирован, и в каждом из этих случаев дескриптор считаются готовыми к чтению.)

Короче (только для чтения), мы можем понять это как:

select не блокирует это означает, что следующий вызов функции ввода с помощью O_NONBLOCK не возвратит ошибку с errno==EWOULDBLOCK. [Обратите внимание, что "следующая" - это моя интерпретация вышеизложенного.]

Если кто-то допускает эту интерпретацию, то два одновременных вызова select могут возвращать тот же FD, что и читаемый. На самом деле, даже если они не являются параллельными, но первый поток вызывает select с некоторым читаемым FD, а позже, например, read, второй поток, вызывающий select между ними, может возвращать FD как читаемый для второго потока,

Теперь соответствующая часть для "пробуждения" части вопроса такова:

Если ни один из выбранных дескрипторов не готов к запрошенной операции, pselect() или select() блокируется до тех пор, пока, по меньшей мере, одна из запрошенных операций не станет до тех пор, пока не произойдет тайм-аут, или пока он не будет прерван сигналом.

Здесь ясно, что приведенная выше интерпретация предполагает, что все ожидающие вызовы возвратятся.

Ответ 2

Я только что нашел ошибку из-за этого вопроса: У меня есть два потока, выбирающих один и тот же сокет, и вызывается accept, когда fd возвращается как isset(). Фактически выбор возвращается для обоих потоков, fd isset() для этого fd в обоих потоках, и оба потока вызывают accept(), один выигрывает, а остальные блоки ждут другого соединения.

Таким образом, на самом деле select вернется во всех потоках, которые он блокирует для одного и того же fd.

Ответ 3

Они должны все просыпаться, все возвращают одинаковое значение результата, и все они делают то же самое с наборами FD. Они все задают один и тот же вопрос, поэтому они должны получить одинаковый ответ.

Предполагается, что select() должен делать, согласно документации POSIX, которая была приведена здесь, и моей простой 25-летней эксцессией с ней, заключается в том, чтобы вернуть число FD, которые можно читать, записывать и т.д. это мгновение. Поэтому было бы совершенно неверно, если бы все одновременные вызовы select() не возвращали одно и то же.

Функция select() не может предсказать будущее, то есть какой поток на самом деле собирается читать или писать, и, следовательно, какой поток будет успешным в этом. Они утверждают. Это проблема громоподобного стада.