什么是fifo的缓冲版本?

时间:2012-09-28 16:43:54

标签: c linux ipc named-pipes file-descriptor

背景
我正在玩一个FIFO,每当我尝试在我的fifo上写字时它会阻塞,直到有人正在读取fd的另一面:

int fd;
char buffer[100] = {0};
char * myfifo = "/tmp/myfifo";    

mkfifo(myfifo, 0666);
printf("What would you like to send?\n");
fgets(buffer, 100, stdin);

if((fd = open(myfifo, O_WRONLY)) < 0)
    printf("Couldn't open the FIFO for writing!\n");
else {
    write(fd, buffer, strlen(buffer));
    close(fd);

此代码有效,但它会阻塞,直到我读取/tmp/myfifo方并获取数据。当我改变代码时:

if((fd = open(myfifo, O_WRONLY | O_NONBLOCK)) < 0)

然后打开失败并显示错误No such device or address,除非我有人坐在“阅读”一侧。

分析 根据{{​​1}}的{​​{3}}:
fifo()

所以这是预期的操作。

问题

根据我的实验和我正在阅读的内容...我必须假设 FIFO是一种非排队的非缓冲机制,只有在有进程和等待数据。

是否有一种不同的通信机制可以在非阻塞的缓冲区域中工作,基本上是缓冲的FIFO,或者我是否必须为此创建自己的消息存储/通知系统?

修改

我说我在“玩”,这实际上是非常具有描述性的。我正在尝试学习各种IPC机制(FIFO,套接字和管道)的细节。我正努力学习使用The kernel maintains exactly one pipe object for each FIFO special file that is opened by at least one process. The FIFO must be opened on both ends (reading and writing) before data can be passed. Normally, opening the FIFO blocks until the other end is opened also.并了解可以用来唤醒调用select的睡眠进程。原因是它是通信驱动程序的一部分我正在分析端口到新平台。
我将其从原始帖子中排除,因为它有点无关紧要。我只是想确保我能理解(目前)FIFO,如何使用它们,它们的局限性以及其他IPC机制。因此,我最初的假设/关于“更好”版本的FIFO的假设/问题将存储数据并且可以无阻塞地写入。

1 个答案:

答案 0 :(得分:1)

FIFO不仅是缓冲的,而且基本上都是FIFO。 FIFO只不过是内核中的缓冲区。

讨论:内核有一个策略,它拒绝将数据写入缓冲区,除非进程打开FIFO进行读取。此行为类似于管道和TCP连接,但如果没有管道或TCP连接的读取器,内核将实际发出写入过程的信号,终止它(除非您安装处理程序)。这种行为允许我们按照我们期望的方式将命令串起来,例如,

hexdump file.dat | head

hexdump程序在head读取几行后被杀死。这是99%的时间我们想要的,hexdump不需要任何特殊代码来实现这一点。

解决方案:如果您描述一些有关您要解决的问题的更多背景信息,那将会有所帮助。

  1. 如果您想要一个客户端/服务器系统,其中服务器对可以由客户端读取的消息进行排队,则可以使用Unix域套接字实现此目的。 Unix域套接字类似于FIFO,但在各种方面更灵活。 (大多数数据库服务器比其他类型的IPC更喜欢Unix域套接字。)

  2. 如果您希望能够存储持久性队列,应用程序可以独立地将消息排入队列并使其出列,那么您将需要使用普通文件。

  3. 不幸的是,“玩一个FIFO”并不多。如果你想在IPC中进行一次很好的练习,可以尝试编写一个使用Unix域套接字或TCP的聊天服务器(或者同时使用两者,这并不困难)。您可以使用telnetnc(netcat)作为客户端。 (确保你有netcat的“OpenBSD”版本。)