什么是先进先出的缓冲版本?

Posted

技术标签:

【中文标题】什么是先进先出的缓冲版本?【英文标题】:What would be a buffered version of a fifo? 【发布时间】:2012-09-28 16:43:54 【问题描述】:

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

分析 根据man pagefifo():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,它将存储数据并且可以在没有阻塞的情况下写入。

【问题讨论】:

听起来你要的是message queue。 【参考方案1】:

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

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

hexdump file.dat | head

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

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

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

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

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

【讨论】:

很好的输入!我正在做的事情有点复杂,我试图通过“玩耍”来保持简单(我已经在原始帖子中添加了一个编辑仅供参考)。最终目标是在单个嵌入式 Linux 板上(非网络)上的多进程。所以我正在尝试查看 IPC 的简单示例。 FIFO 看起来很简单,但后来我被流中阻塞的事实卡住了。想了解为什么我被阻止在那里以及是否可以避免。

以上是关于什么是先进先出的缓冲版本?的主要内容,如果未能解决你的问题,请参考以下文章

页面调度先进先出算法(FIFO) 用C语言描述 欢迎高手前来挑战

队列排序,先进先出

队列 先进先出,先进后出,优先级队列

队列Queue FIFO先进先出 栈Stack FILO先进后出

拦截先进先出

Stack和Queue:后进先出和先进先出和Java 实现后进先出(LIFO)及Stac和Java集合类: SetListMapQueue使用场景梳理 - .Little Hann