Невозможно открыть FIFO для записи

Сторона программы «Сервер»:

#define RESP_FIFO_NAME "response"

/* Global Variables */
char *cmdfifo = CMD_FIFO_NAME; /* Name of command FIFO. */
char *respfifo = RESP_FIFO_NAME; /* Name of response FIFO. */

int main(int argc, char* argv[]) {
int infd, outfd; /* FIFO file descriptors. */

... // blah blah other code here

/* Create command FIFO. */
if (mkfifo(cmdfifo, FIFO_MODE) == -1) {
    if (errno != EEXIST) {
        fprintf(stderr, "Server: Couldn’t create %s FIFO.\n", CMD_FIFO_NAME);
        exit(1);
    }
}

/* Create response FIFO. */
if (mkfifo(respfifo, FIFO_MODE) == -1) {
    if (errno != EEXIST) {
        fprintf(stderr, "Server: Couldn’t create %s FIFO.\n", RESP_FIFO_NAME);
        exit(1);
    }
}
/* Open the command FIFO for non-blocking reading. */
if ((infd = open(cmdfifo, O_RDONLY | O_NONBLOCK)) == -1) {
    fprintf(stderr, "Server: Failed to open %s FIFO.\n", CMD_FIFO_NAME);
    exit(1);
}

        /* Open the response FIFO for non-blocking writes. */
if ((outfd = open(respfifo, O_WRONLY | O_NONBLOCK)) == -1) {
            fprintf(stderr, "Server: Failed to open %s FIFO.\n", RESP_FIFO_NAME);
            perror(RESP_FIFO_NAME);
            exit(1);
        }

Программа выводит вывод:

Server: Couldn’t create response FIFO.

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


person ICantNameMe    schedule 06.05.2013    source источник
comment
Вы должны указать имя, использованное в вызове mkfifo(), в сообщении об ошибке, то есть respfifo, а не RESP_FIFO_NAME. Какие FIFO существуют в текущем каталоге (программы при ее запуске)? Вы уверены, что хотите включить в имя FIFO угловые скобки (или это сообщение об ошибке из другой версии кода)? Вы можете включить в вывод errno и strerror(errno); это помогло бы диагностировать проблему (EEXIST против EPERM против ...).   -  person Jonathan Leffler    schedule 06.05.2013
comment
Используйте perror или strerror, чтобы узнать точную ошибку.   -  person Thomas Ruiz    schedule 06.05.2013
comment
RESP_FIFO_NAME — макроконстанта препроцессора #define. Я добавлю это сейчас. Я предположил, что это не имеет значения, поскольку это был просто строковый литерал с прямой заменой текста. Да, я сейчас воспользуюсь perror и посмотрю, в чем реальная проблема.   -  person ICantNameMe    schedule 06.05.2013
comment
perror(RESP_FIFO_NAME) выводит <RESP_FIFO_NAME>: No such device or address, что, по-видимому, ENXIO   -  person ICantNameMe    schedule 06.05.2013
comment
Интересно: ENODEV не указан как возможная ошибка из-за mkfifo(2) в Mac OS X. Вы выполняли какие-либо chdir() операции? Я вижу, что удаление угловых скобок не меняет результат. Что такое FIFO_MODE? Команда FIFO уже существует?   -  person Jonathan Leffler    schedule 06.05.2013
comment
FIFO_MODE это 0644 = rw-r--r--. Я вообще не использовал никаких chdir, все файлы, с которыми я имею дело, находятся в одном каталоге. Я только что создал cmdfifo вверху файла main. Он может существовать уже из предыдущих исполнений программы. Если я сдвину команду open для respfifo как можно ниже, вместо этого я получу ошибку read(infd, msgbuf, MSGSIZE+1) == -1, которая возвращает Resource temporarily unavailable из вызова perror.   -  person ICantNameMe    schedule 06.05.2013
comment
На самом деле первое выполнение дает мне No such device or address, затем, если я запущу его снова, не удаляя файл FIFO, я получаю ошибку Resource temporarily unavailable.   -  person ICantNameMe    schedule 06.05.2013


Ответы (1)


Из справочной страницы:

Процесс может открыть FIFO в неблокирующем режиме. В этом случае открытие только для чтения завершится успешно, даже если со стороны записи еще никто не открывал; открытие только для записи не удастся с ENXIO (нет такого устройства или адреса), если другой конец уже не был открыт.

Вы должны открыть это в «клиенте».

person Thomas Ruiz    schedule 06.05.2013
comment
Хорошо. Тогда я был сбит с толку его инструкциями, потому что он сказал: /* Create and appropriately open the command and reply FIFOs. */ Что было до разветвления процесса для создания искусственного «Клиентского» (дочернего) процесса. Я открыл его в процессе клиента, но это происходит позже в программе... - person ICantNameMe; 06.05.2013
comment
Это интересно, но повлияет на открытие FIFO, а не на его создание, что, по-видимому, и является причиной возникновения проблемы. @ICantNameMe: вы уверены, что это ваш mkfifo() не работает? Вы случайно не копировали и не вставляли блок сообщения об ошибке, не меняя само сообщение? - person Jonathan Leffler; 06.05.2013
comment
Не работает не mkfifo, а команда open для O_WRONLY | O_NONBLOCK дает мне ENXIO: no such device or address error. Я не знаю, почему он выдает мне эту ошибку, потому что я еще не могу получить доступ к файлу клиента, поэтому я думаю, что это означает, что я должен переместить это дальше в программе до тех пор, пока не будет форк, иначе никто не сможет прочитать то, что я я пишу? - person ICantNameMe; 06.05.2013
comment
Я тоже так думал, поэтому, я думаю, вам нужно открыть этот fifo в клиенте. - person Thomas Ruiz; 06.05.2013
comment
@ICantNameMe: ваш фрагмент кода совершенно сбивает с толку, если это open() (которое вы не показываете) терпит неудачу - это требует отрицательного голосования. Описание сообщения об ошибке, которое нашел Томас, полностью подходит для открытия FIFO для записи только с O_NONBLOCK. Может быть, вам следует подождать, чтобы открыть ответный FIFO для записи, пока у вас не появится клиент с командой FIFO, открытой для записи? Или, может быть, вы не хотите O_NONBLOCK... - person Jonathan Leffler; 06.05.2013
comment
Извините, я совершенно забыл включить это. Я думал, что сделал это по какой-то причине. Это там сейчас. Извините за путаницу. - person ICantNameMe; 06.05.2013