2013-09-10 2 views
1

Скажем, у меня есть fifo (named pipe), который открывается несколько раз из нескольких процессов или потоков. Все они будут вызывать select() для чтения одновременно. Если писатель приходит и записывает, скажем, один байт этого fifo, все будут заблокированы select() вызовы возвращаются одновременно или будет выбран только один поток и вернуться из select()?одновременный выбор из именованного канала

Есть ли какие-либо спецификации по этому вопросу или это будет зависящим от системы?

Причина, по которой я спрашиваю, что я хочу реализовать события сброса вручную, связанные с Windows, используя fifos. Для события ручного сброса требуется, чтобы при сигнале события все ожидающие потоки были освобождены (а не только как событие автоматического сброса).

Я мог бы использовать pthread conds для этого, но мое требование состоит в том, чтобы события делились несколькими процессами.

Спасибо.

ответ

1

Если писатель приходит и пишет, скажем, один байт в этом ФИФО, будет все заблокирован выберите() вызовы возвращают одновременно или будет выбран только один поток и вернуться из отборных()?

Будет состояние гонки. Система начнет запускать потоки в некотором случайном порядке, пока один из них не прочитает данные, не опустошит буфер и не пробудит другие потоки.

Есть ли какие-либо спецификации по этому вопросу или это будет зависящим от системы?

Это будет зависеть от системы, расположения приложения, структуры кода. Это будет одно великое неопределенное поведение.

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

Вы кодируете Linux/Posix? Используйте функцию tee вместо чтения, чтобы потоки записывали код состояния обратно в трубку, чтобы сигнализировать о том, что они пробуждаются. Затем сбросьте трубку, читая данные обратно в поток управления.

есть, сделайте следующее:

В рабочих потоков: выберите (и блок). В контрольном потоке: напишите один байт. Теперь выбор не блокируется. Рабочие потоки пробуждаются. Теперь сделайте необязательный тройник (один байт) в рабочих потоках и напишите один байт обратно в трубу в каждом потоке. В контрольном потоке: чтение и подсчет байтов. Если все волны рабочей нити пробуждаются, сделайте еще один байт, чтобы стереть первый байт, который вы написали. Теперь выбор теперь блокируется.

Обратите внимание, что вы не можете ввести выбор еще раз, пока не завершите всю процедуру. Вам могут понадобиться две такие трубы.

+0

Большое спасибо. Таким образом, вы говорите, что все потоки будут пробуждены от выбора, но это может не произойти немедленно, поэтому нам нужно предотвратить состояние гонки, когда событие будет сброшено между этими пробуждениями. К сожалению, поток управления не знает вообще, сколько ожидающих потоков, поэтому мне, возможно, придется сделать что-то более сложное, например, написать байт, прежде чем выбрать «зарегистрировать» ожидающий поток. Я подумаю об этом. –

+0

Я думаю, мне нужен какой-то межпроцессный rwlock.Затем каждый поток, прежде чем делать select(), заблокирует его в режиме чтения, затем разблокирует его после возвращения из select, ему не нужно ничего читать из fifo. Поток, который выполняет ResetEvent, просто блокирует rwlock в режиме записи и считывает байт, который был записан во время SetEvent, а затем разблокирует rwlock. Это заставит поток управления ждать, пока каждый ожидающий поток не вернется из выбора. Так что просто нужно найти, как реализовать interprocess rwlock. –

+0

Похоже, flock() может работать на это. –

Смежные вопросы