Как мне выполнить неблокирующую команду fopen на именованном канале (mkfifo)?

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

В частности, я пишу программу на C, которую можно запускать с графическим интерфейсом или без него (написано на Java).

В программе C я успешно создаю именованные каналы с помощью mkfifo, однако когда я это делаю

FILE* in = fopen(PIPE_IN, "r"); /* Where PIPE_IN is the filename*/

fopen не возвращается, пока графический интерфейс не откроет этот канал для записи. Я хочу, чтобы этот канал был готов к чтению один раз (если) графический интерфейс решит записать в него - я помещу дескриптор файла в вызов select (). Разумно ожидать, что графический интерфейс Java может никогда не запуститься, поэтому я не могу полагаться на него, чтобы открыть другой конец канала в какой-либо конкретной точке или даже вообще.

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

Какие-либо предложения?

(Это работает в системе Linux)


person Zxaos    schedule 24.02.2009    source источник
comment
Вам нужно открыть выходную трубу перед запуском select () на входной трубе?   -  person Tim Post♦    schedule 24.02.2009
comment
@tinkertim - я полагаю, что технически нет - я установил их обоих в функции настройки, но я мог просто сначала настроить выходной канал, а затем вызвать select, почему?   -  person Zxaos    schedule 24.02.2009


Ответы (1)


Вы можете open() свой канал O_RDONLY | O_NONBLOCK, и если вам нужен поток C, вы можете получить его с помощью fdopen(). Однако может быть проблема с select() - AFAIK, канал fd, открытый для чтения, который не имеет записи, всегда готов к чтению, а read() возвращает 0, поэтому select() будет срабатывать бесконечно.

Неуклюжий способ преодолеть это - открыть трубу O_RDWR; то есть иметь хотя бы одного писателя (вашу программу на C ++). Что в любом случае решило бы вашу проблему.

person jpalecek    schedule 24.02.2009
comment
Я сделаю это для читателя, но я не могу установить O_NONBLOCK для выходного канала ... - person Zxaos; 24.02.2009
comment
Стандарт POSIX гласит (о select ()): дескриптор считается готовым к чтению, если вызов функции ввода с очисткой O_NONBLOCK не блокирует, независимо от того, будет ли функция успешно передавать данные. (POSIX.1: 2008). - person Jonathan Leffler; 24.02.2009
comment
Открытие канала O_RDWR приведет к тупиковой ситуации, когда программа читает (или записывает) - если на самом деле нет другого процесса, также с открытым каналом. - person Jonathan Leffler; 24.02.2009
comment
@Jonathan Leffler - Но могу ли я открыть его RDWR и просто опросить, чтобы узнать, когда другой процесс действительно написал в него? Это не должно вызывать тупиковых ситуаций, верно? - person Zxaos; 24.02.2009
comment
Да, и это должно быть заблокировано в select (). Нет таких решений для записи конца канала, вероятно, лучшее, что вы могли бы сделать, это открыть конец записи после того, как вы получили какое-то приглашение от программы Java. - person jpalecek; 24.02.2009
comment
@jpalecek Да, я понял, что должен был сделать прошлой ночью, подумав о том, почему Тинкертим спросил о порядке в комментарии к исходному вопросу. - person Zxaos; 24.02.2009