我们有一个运行 Linux 2.6.32.20 的基于 ARM9 的嵌入式板。该设备是一个摄像机,其相关的捕获/压缩硬件将数据放入 ARM 内存中的输入 fifo,然后 ARM 从用户空间访问该输入FIFO。我们还有一个用于高级控制的编码器驱动程序。
应用程序级代码中的一个线程检查此用户空间 fifo,并在有数据时通过套接字将其发送出去。为了避免该线程需要轮询用户空间 fifo 以获取数据的开销,我们对驱动程序进行了非常简单的 read() 调用,实际上它只是挂起,直到 fifo 中有任何数据(没有真正“读取”到read() 调用中提供的缓冲区)。然后这个 read() 调用返回,线程继续从 fifo 读取数据,直到它为空,然后通过调用假的 read() 调用再次挂起。
该系统非常有效,通过在检测到丢帧之前可以传输多少网络流来衡量。但是我们已经确定,使用虚假的 read() 调用会导致 Linux“top”实用程序报告我们的应用程序使用大量 CPU。
我们已经构建了 2 个版本的应用程序 - 一个与上面一样运行,另一个相同,只是它从不调用假 read(),而是通过干预 usleep() 调用轮询 fifo。当我们查看“top”报告的 2 种情况下每个发送 5 个流的 CPU 使用率时,我们得到:
1) read() 版本:CPU 12%
2) usleep() 版本:CPU 4%
当然,现实中的轮询效率较低,如果我们忽略“top”所说的内容,而只是在我们看到丢帧之前测量两个版本可以同时传输多少网络流,那么上面的版本 1 获胜。
我们已经验证了上面的 read() 调用运行正常。如果某些错误导致 read() 调用立即返回,即使 fifo 中没有数据,那么线程最终将执行昂贵的连续轮询。但这种情况并非如此; read() 调用使线程每秒准确运行 30 次。
我们认为我们的玩具busybox版本的“top”可能采取了一些捷径——但这些结果并没有出现在top用来计算其显示数字的/proc//stat中的原始数字中。
这个问题一定是Linux内核本身如何收集/proc//stat中显示的数字的一些限制。
如果有人理解为什么会这样,请指出我正确的方向。谢谢!