1

背景
我正在玩 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,除非我有人坐在“读取”侧。

分析 根据手册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.

所以这是预期的操作。

问题

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

是否有不同的通信机制可以在非阻塞缓冲庄园中工作,基本上是缓冲 FIFO,还是我必须为此制作自己的消息存储/通知系统?

编辑

我说我在“玩弄”,这在这里实际上非常具有描述性。我正在尝试了解各种 IPC 机制(FIFO、套接字和管道)的来龙去脉。我正在努力学习使用select()和理解什么可以用来唤醒调用 select 的睡眠进程。原因是它是我正在分析移植到新平台的通信驱动程序的一部分。
我将其从原始帖子中排除,因为它有点无关紧要。我只是想确保我能理解(目前)FIFO、如何使用它们、它们的限制以及其他 IPC 机制。因此,我最初的假设/问题是关于“更好”版本的 FIFO,它将存储数据并且可以在没有阻塞的情况下写入。

4

1 回答 1

2

FIFO 不仅是缓冲的,而且基本上是 FIFO 的全部内容。FIFO 只不过是内核中的一个缓冲区。

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

hexdump file.dat | head

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

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

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

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

不幸的是,“玩弄 FIFO”并没有什么可做的。如果您想在 IPC 方面进行一次很好的练习,请尝试编写一个使用 Unix 域套接字或 TCP(或同时使用两者,这并不难)的聊天服务器。您可以使用telnetor nc(netcat) 作为客户端。(确保您拥有 netcat 的“OpenBSD”版本。)

于 2012-09-28T17:21:24.630 回答