Why does my program hang when opening a mkfifo-ed pipe?

前端 未结 2 798
忘掉有多难
忘掉有多难 2020-11-30 09:35

I use mkfifo to create a named pipe. Then I use the following program to open it. However, the program hangs at the line \"fopen\". Is there something wrong here?

         


        
相关标签:
2条回答
  • 2020-11-30 09:39

    Try passing "w" as the mode to fopen. "rw" is not a valid mode argument for fopen, and even if it was, you probably don't want to both read and write to the FIFO in the same process (although it is possible, see below).

    As an aside, the correct mode argument for opening a file for both reading and writing is either "r+" or "w+" (see the answers to this question for the differences).

    This program will correctly write to the 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;
    }
    

    Note that fopen in the above program will block until the FIFO is opened for reading. When it blocks, run this in another terminal:

    $ cat /tmp/myFIFO
    Hello, world!
    $ 
    

    The reason why it blocks is because fopen does not pass O_NONBLOCK to open:

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

    Some background on how FIFOs are opened

    Read-only, without O_NONBLOCK: open blocks until another process opens the FIFO for writing. This is the behavior when using fopen with mode argument "r".

    Write-only, without O_NONBLOCK: open blocks until another process opens the FIFO for reading. This is the behavior when using fopen with mode argument "w".

    Read-only, with O_NONBLOCK: open returns immediately.

    Write-only, with O_NONBLOCK: open returns an error with errno set to ENXIO unless another process has the FIFO open for reading.

    Info from "Advanced Programming in the UNIX Environment" by W. Richard Stevens.

    Opening a FIFO for read and write

    Opening a FIFO for reading and writing within the same process is also possible with Linux. The Linux FIFO man page states:

    Under Linux, opening a FIFO for read and write will succeed both in blocking and nonblocking mode. POSIX leaves this behavior undefined. This can be used to open a FIFO for writing while there are no readers available. A process that uses both ends of the connection in order to communicate with itself should be very careful to avoid deadlocks.

    Here's a program which writes to and reads from the same 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;
    }
    

    It does not block, and returns immediately:

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

    Note that this is not portable and may not work on operating systems besides Linux.

    0 讨论(0)
  • 2020-11-30 09:40

    The process blocks until the other end of the pipe gets opened.

    0 讨论(0)
提交回复
热议问题