C、是否可以阻塞进程直到再次打开管道?

C, is it possible to block the process untill the pipe is opened again?

我正在组装一个类似服务器的进程,它从命名管道接收数据和 returns 一些输出。

众所周知,当管道打开进行读取时,它会阻塞进程,直到另一个进程打开管道进行写入。 (除非设置了非阻塞标志。) 当另一个进程打开管道并写入时,我们可以得到这样的输入:

...
opened_pipe = fopen(argv[1], "r")
while(1)
   {
   if ( fgets(readbuf, FIFO_READLEN, opened_pipe) != NULL )
       { \ process the input from the writer  }
   else
       {
       \ this is the branch when the writer closed his end of the pipe and reader gets EOF
       \ usually one exits here
       \ but I would like to freeze the process and wait until another writer comes
       \ (like a server-like application would do)
       }
   }

但是当作者退出这个 while 进入无意义的循环。 如果 reader 返回到初始状态会更好 - 进程将被阻塞,直到管道再次连接到另一端。可以这样做吗?

PS

我试图在我的程序中创建一个虚拟编写器,它打开与 w 相同的管道,并始终在 fgets 的循环中保持打开状态。但这对我不起作用。也许我做错了什么。这招有可能吗?

也可以不断地关闭和重新打开 while 内的管道。但我想使用 pipestdin 作为输入流。不如在节目中一视同仁。那么,是否可以通过 fopen 使用一些 "stdin" 文件名重新打开 stdin 流?

不确定我完全理解你的问题,但一般来说,当从没有打开写入端的管道或 FIFO(又名命名管道)读取时,你会读取 EOF。当 fgets() 读取 EOF 时,这将导致缓冲区中的第一个字节为 0。您可以检查一下,在这种情况下,关闭 FIFO 并重新打开它,重新进入循环。

类似于(坚持你的伪代码段):

while (1)
{
    opened_pipe = fopen(argv[1], "r")
    while(1)
    {
        if ( fgets(readbuf, FIFO_READLEN, opened_pipe) == NULL ) {...}
        else if (!readbuf[0])
        {
            fclose(opened_pipe);
            break;
        }
    }
}

编辑: 根据您在这里的评论,我觉得您可能想要使用 Unix 域套接字 而不是 先进先出。因此,您可以 accept() 个连接并在等待新连接的同时单独处理它们。

只需在服务器进程中打开您的 FIFO 两次 - 第一次用于读取,然后用于写入。这样做(打开它进行写入)将确保如果所有客户端都放弃 FIFO,您的进程将不会看到 EOF。

这是简短的演示:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>

#include <sys/types.h>
#include <sys/stat.h>

#define FIFO_NAME "/tmp/fifo"

int main()
{
    if (mkfifo(FIFO_NAME, S_IRUSR | S_IWUSR | S_IWGRP) == -1)
    {
        perror("mkfifo");
        exit(EXIT_FAILURE);
    }

    FILE *readFd  = fopen(FIFO_NAME, "r");
    FILE *writeFd = fopen(FIFO_NAME, "w");

    char c;
    for (;;)
    {
        c = fgetc(readFd);
        fprintf(stdout, "Read char: %c\n", c);
    }
}