管道-fifo

本文详细阐述了FIFO命名管道的创建、实质、使用方式及其特性,包括打开与关闭方式、长度限制、竞争问题及非阻塞模式的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一. 简介

    FIFO 又称为 named pipe、命名管道,用于在不相关的进程之间传递数据,可以通过命令行创建:

        mkfifo filename

    也可以通过程序创建:

        int mkfifo(const char *filename, mode_t mode);

    此外,还可以利用 mknod,但该命令非规范。


二. 实质

    FIFO 是磁盘上一个真实的文件,可以像删除普通文件那样,在命令行用 rm 删除,在程序中用 unlink 删除。

    使用 ls 查看结果如下:

        prwxrwxrwx 1 rick users 0 XXXX-XX-XX XX:XX /named-pipe|

    输出结果中第一个字符为 p,最后一个字符为 |。


三. 深入

    FIFO 使用 open 和 close 打开和关闭(底层 IO 库的使用场景,虽然它们并不是 ANSI C 的一部分)。其最重要的内容,就是 open 操作。

1. 使用 open 打开 FIFO 时,不能使用 O_RDWR 模式,因为管道是单向的,如果被以读/写的方式打开,进程就会从这个管道读回它自己的输出。

2. 打开 FIFO 和打开普通文件的区别,在于对 open_flag 的O_NONBLOCK 选项的用法。有以下 4 种组合:

    open(const char *path, O_RDONLY);

    该模式下,open 调用将阻塞。当另一个进程以写方式打开同一个 FIFO 后,两个程序继续运行。读进程和写进程在 open 调用处取得同步。

    open(const char *path, O_WRONLY);

    此时 open 调用同样将阻塞,直到另一个进程以读方式打开同一个 FIFO。

    open(const char *path, O_RDONLY | O_NONBLOCK);

    即使没有其它进程以写方式打开该 FIFO,该 open 调用也将成功并立即返回。总是成功

    open(const char *path, O_WRONLY | O_NONBLOCK);

    该调用总是立即返回。如果已经有一个进程以读方式打开 FIFO,那么可以通过其返回的文件描述符操作该 FIFO。但如果没有进程以读方式打开 FIFO,该调用将返回 -1 错误。如果没有以读方式打开,则失败,如果已经以读方式打开,则成功

3. O_NONBLOCK 对读写的影响

    对一个空的、阻塞的 FIFO(即没有用 O_NONBLOCK 方式打开) 的 read 调用将等待,直到有数据可以读时才继续进行。与此相反,对一个空的、非阻塞的 FIFO 的 read 调用将立刻返回 0。

    对一个完全阻塞的 FIFO 的 write 调用将等待,直到数据可以写入。

    即阻塞/非阻塞的原始含义

4. FIFO 的长度

    系统对任一时刻在一个 FIFO 中可以存在的数据长度是有限制的,由 #define PIPE_BUF 定义,通常在 limits.h 文件中,一般为 4096。系统规定:在一个以 O_WRONLY 方式打开的 FIFO 中,如果写入的数据长度小于等于 PIPE_BUF,那么或者写入全部字节,或者一个字节都不写入。如果写入的数据长度大于 PIPE_BUF,将可能写入部分数据并返回写入的字节数,也可能无法写入任何数据,返回 0。

5. 竞争

    如果同时有多个进程往一个 FIFO 中写,此时必须保证数据不相互交错或者覆盖。 FIFO 的机制可以保证不覆盖,在一个 PIPE_BUF 范围内也不会交错,唯一的问题是,多个 PIPE_BUF 之间有可能交错。系统确保,如果所有的写请求是发往一个阻塞的 FIFO,并且每个写请求的数据长度小于等于 PIPE_BUF 字节,那么数据就不会交错在一起。


四. 思考

1. 做过测试:读写进程分别打开 FIFO 后,在写进程 write() 成功、读进程尚未 read() 之前,发现磁盘上的 FIFO 大小仍然为 0。考虑到底层的文件操作并没有 flush() 命令,即使 close(),也不会做类似 flush() 的操作,因此,磁盘上的 FIFO 大小,是否一直为 0?也即,虽然可以把 FIFO 视为磁盘文件,但其实质并不是?

2. 关于 三 中的 4、5 两点,前提都是阻塞的 FIFO。对于非阻塞的情况都没有提到,那么,非阻塞的 FIFO 是什么情况?同时,是不是意味着,建议使用阻塞方式而不是非阻塞方式?

### AXI4-Stream FIFO 实现与应用 AXI4-Stream 是一种用于高速数据流传输的接口标准,特别适用于FPGA 和 ASIC 设计中的数据流水线处理。AXI4-Stream 接口不支持地址信号,仅提供有效载荷传输功能。 #### 协议规范概述 AXI4-Stream 定义了一组简单的握手信号来控制数据流动: - `TVALID` 表明源端有有效的数据可以发送 - `TREADY` 表示接收方准备好接受新数据 - `TDATA` 为实际的数据位宽 - 可选信号如 `TLAST`, `TKEEP`, `TSTRB`, `TID`, `TDEST` 提供额外的功能特性[^1] 这些信号共同作用确保了高效可靠的数据传输机制,在不同模块间建立无缝连接。 #### FIFO 的基本原理 FIFO (First In First Out) 缓冲器是一种先进先出结构,主要用于解决生产者消费者模型下的速率匹配问题。对于 AXI4-Stream 来说,FIFO 能够平滑瞬态负载波动并缓解上下游组件之间的速度差异。 ```verilog module axi_stream_fifo #( parameter DATA_WIDTH = 32, parameter DEPTH = 8 )( input wire clk, // Clock signal input wire rst_n, // Reset signal // Slave Interface input wire s_axis_tvalid, output reg s_axis_tready, input wire [DATA_WIDTH-1:0] s_axis_tdata, // Master Interface output reg m_axis_tvalid, input wire m_axis_tready, output reg [DATA_WIDTH-1:0] m_axis_tdata ); // Internal signals and logic here... endmodule ``` 此 Verilog 模块展示了如何创建一个基于 AXI4-Stream 的简单同步 FIFO 结构。通过调整参数 `DATA_WIDTH` 和 `DEPTH` ,可以根据具体应用场景定制化设计满足需求的 FIFO 缓存大小和宽度。 #### 使用案例分析 在图像处理管道中,AXI4-Stream FIFO 常被用来作为像素数据缓冲区;在网络通信领域,则可用于暂存待发送或已接收到的数据包片段。此外,在音频编解码过程中也广泛采用此类技术来进行采样率转换及时钟域跨越操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值