Linux fifo 缓冲采坑

Linux fifo 缓冲采坑,第1张

本文记录了我在使用 fifo(命名管道)的过程中由于缓冲踩的坑。

事情的经过是这样的:我有一个 python 脚本,它会实时向标准输出打印数据,现在我想把这些打印到的标准输出数据导入 FIFO 中,并且在另一个 Qt 程序中从 FIFO 读取数据,于是我开始了下述 *** 作。

首先用 mkfifo tmpfifo 创建了一个 FIFO 文件,然后以下述方式运行我的 python 脚本

另一边创建了一个 Qt 程序打开这个 FIFO 读取数据

两个程序都运行后,出现了一种比较诡异的现象:python 脚本向 FIFO 写入了大量数据后,Qt 程序才会从 readLine() 函数返回,正常情况下应该是 FIFO 写入一行数据,Qt 程序就能够从 FIFO 读出一行数据,但实际情况不是这样,当 FIFO 被写入了大量数据后,才允许从 FIFO 另一端读取数据。

我琢磨了一下午才想到是缓冲区的问题。

C 标准库 IO 函数分为三种缓冲类型:

那么 FIFO 是属于哪一种缓冲区呢?我在 APUE 里找到了下面这几句话:

因此,FIFO 是全缓冲设备,这也解释了为什么上面介绍的 python 脚本将数据打印到标准输出时数据是一行一行的显示,而打印到 FIFO 时,数据只能是一大块一大块的读取。

找到了问题的缘由,我更改了 python 脚本的 print() 函数:

每写入一行数据,自动刷洗数据,这样就成功解决了问题。

时钟80MHz。
读时钟50MHz。
Burst_Len = 120 , 也就是要求至少安全写入120个数据。
连续写入和连续读取,无空闲时间,写入后立即开始读取 ,读写宽度相同。

速率 > 读速率,FIFO迟早会被写满,但它要求至少写入120个数据后FIFO不满。
写入120个数据耗时 120 125 ns = 1500 ns 。
写入开始后FIFO内数据以 30M/Date 速率增加。
数据增加持续了 1500 ns ,FIFO最小深度: 00000015 30000000 = 45

例子-1 总结公式:

写时钟80MHz。
读时钟50MHz。
Burst_Len = 120 ,也就是要求至少安全写入120个数据。
写入后立即开始读取 ,读写宽度相同。
2个时钟中有1个数据写入(写速率: 80M 1/2 = 40M )。
4个时钟中有1个数据读出(读速率: 50M 1/4 = 125M )。

FIFO迟早会被写满 ,但它要求至少写入120个数据后FIFO不满。
写一个数据耗时: 2/80MHz = 25ns
需要至少写入120数据,耗时: 25 120 = 3000ns
例子2只是读写速率和例子1不同,可以直接用的公式(1) :
FIFO_DEPTH > (写速率-读速率) Burst_Len/写速率 = (40M-125M)120/40M = 83

写时钟30MHz。
读时钟50MHz。
Burst_Len = 120 ,也就是要求至少安全写入120个数据。
连续写入和连续读取,无空闲时间,写入后立即开始读取 ,读写宽度相同。

FIFO_DEPTH > 1 即可。读速率比写速率快,数据不会滞留。

写时钟30MHz。
读时钟50MHz。
Burst_Len = 120 ,也就是要求至少安全写入120个数据。
2个时钟中有1个数据写入(写速率: 30M 1/2 = 15M )。
4个时钟中有1个数据读出(读速率: 50M 1/4 = 125M )。

虽然写时钟小于读时钟频率,但是,宏观上写速率大于读速率。可以直接用的公式(1) :
FIFO_DEPTH > (写速率-读速率) Burst_Len/写速率 = (15M-125M)120/15M = 20

当满足以下所有条件时,就可使用公式(1):

当每100个时钟写80个数据时,微观时间上的写速率与数据排列有关,不能将宏观写速率带入式子(1)

读写时钟频率相同。
100个时钟有80个数据写入。
10个时钟有8个数据读出。
Burst_Len = 160 ,也就是要求至少安全写入160个数据 。

宏观上,读写速率相同;当FIFO足够深时,FIFO不会溢出。
微观上,写速率有多种情况:

Burst_Len足够长时,将上面读出写入速率带入公式(1),可得到网上讨论最多的FIFO深度求解公式:

十分不建议直接用公式(2)无脑计算,上式只有Burst_Len足够长,发生back to back write时才适用。

建议根据1~6步骤,判断微观写速率是否均匀,带入式子(1)计算。

以上,仅备忘用途。
可能会有错误。

关于第二个问题,主要现在电路已经做成,有些线已经无法再连接,看能不能从软件方面补救一下。我的FIFO不是靠空满逻辑来读数的,因为我在发送数据给FIFO和从FIFO中读出的数据是一一对应的,有多少数读多少数,不多也不少。但是现在因为FIFO读使能和DMA通道打开之间有个时间差,所以我担心这段时间内没有读到FIFO中的数据,使读上去的数据比预期的要少。

有可能你之后写入的数据就已经是全0了,用一个方法确定,你把输入连到一个常数上,如果到最后有数据输出就说明是对的,要是没数据输出就说明是错的,一般来说FIFO IP核没有问题的,用了好多次了。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/yw/13211344.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-06-21
下一篇 2023-06-21

发表评论

登录后才能评论

评论列表(0条)

保存