Почему моя программа зависает при открытии канала mkfifo-ed? - PullRequest
12 голосов
/ 14 декабря 2011

Я использую mkfifo для создания именованного канала. Затем я использую следующую программу, чтобы открыть его. Однако программа висит на линии «fopen». Здесь что-то не так?

int main(int argc, char** argv) {
char* line = "hello, world!";
FILE* fp = fopen("/tmp/myFIFO", "rw");
fprintf(fp, line);
fclose(fp);
return 0;
}

Ответы [ 2 ]

16 голосов
/ 24 июля 2012

Попробуйте передать "w" в качестве режима для fopen."rw" не является допустимым аргументом режима для fopen, и даже если это так, вы, вероятно, не захотите и читать, и записывать в FIFO в одном и том же процессе (хотя это возможно, см. Ниже).

Кроме того, правильный аргумент режима для открытия файла как для чтения, так и для записи: "r+" или "w+" (см. Ответы на этот вопрос для различий ),

Эта программа будет правильно записывать в FIFO:

#include <stdio.h>
int main(int argc, char** argv) {
    FILE* fp = fopen("/tmp/myFIFO", "w");
    fprintf(fp, "Hello, world!\n");
    fclose(fp);
    return 0;
}

Обратите внимание, что fopen в вышеуказанной программе будет блокироваться, пока FIFO не будет открыт для чтения.Когда он блокируется, запустите его в другом терминале:

$ cat /tmp/myFIFO
Hello, world!
$ 

Причина, по которой он блокируется, заключается в том, что fopen не передает O_NONBLOCK в open:

$ strace -P /tmp/myFIFO ./a.out
open("/tmp/myFIFO", O_WRONLY|O_CREAT|O_TRUNC, 0666) = 3
...

Некоторыефон о том, как открываются FIFO

только для чтения, без блоков O_NONBLOCK: open, пока другой процесс не откроет FIFO для записи.Это происходит при использовании fopen с аргументом режима "r".

только для записи, без блоков O_NONBLOCK: open, пока другой процесс не откроет FIFO для чтения.Это поведение при использовании fopen с аргументом режима "w".

только для чтения, с O_NONBLOCK: open немедленно возвращается.

только для записи, с O_NONBLOCK: open возвращает ошибку с errno, установленным на ENXIO, если только у другого процесса нет открытого FIFO для чтения.

Информация из "Расширенного программирования в среде UNIX" У. РичардаСтивенс.

Открытие FIFO для чтения и запись

Открытие FIFO для чтения и записи в одном и том же процессе также возможно в Linux.Справочная страница Linux FIFO гласит:

В Linux открытие FIFO для чтения и записи будет успешным как в режиме блокировки, так и в режиме неблокирования.POSIX оставляет это поведение неопределенным.Это может быть использовано для открытия FIFO для записи, когда нет доступных читателей.Процесс, который использует оба конца соединения для связи с самим собой, должен быть очень осторожным, чтобы избежать взаимных блокировок.

Вот программа, которая пишет и читает из того же FIFO:

#include <stdio.h>
int main(int argc, const char *argv[]) {
    char buf[100] = {0};
    FILE* fp = fopen("/tmp/myFIFO", "r+");
    fprintf(fp, "Hello, world!\n");
    fgets(buf, sizeof(buf), fp);
    printf("%s", buf);
    fclose(fp);
    return 0;
}

Он не блокируется и сразу возвращается:

$ gcc fifo.c && ./a.out 
Hello, world!

Обратите внимание, что он не переносимый и может не работать в операционных системах, кроме Linux.

9 голосов
/ 14 декабря 2011

Процесс блокируется, пока не откроется другой конец трубы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...