C,是否可以阻止该过程直到管道再次打开?

时间:2015-10-30 20:30:11

标签: c linux ipc stdin named-pipes

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

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

...
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进入无意义的循环。 如果读者返回到初始状态会更好 - 过程被阻塞,直到管道再次连接到另一端。是否可以这样做?

PS

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

还可以不断关闭并重新打开while内的管道。但我想使用pipestdin作为输入流。在程序中以同样的方式对待它们会更好。那么,是否可以通过stdin使用fopen文件名重新打开"stdin"流?

2 个答案:

答案 0 :(得分:1)

不确定我完全理解你的问题,但一般来说,当从管道或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域套接字而不是 FIFO 。因此,您可以accept()连接并在等待新连接时单独处理它们。

答案 1 :(得分:1)

只需在服务器进程中打开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);
    }
}