我们有一个基于ARM9的嵌入式主板,运行
Linux 2.6.32.20.该设备是一个摄像机,其相关的捕获/压缩硬件将数据放入ARM存储器中的输入FIFO,然后ARM从用户空间访问.我们还有一个用于高级控制的编码器驱动程序.
应用程序级代码中的一个线程检查此用户空间fifo,当有数据时,它通过套接字发送出去.为了避免这个线程需要为数据轮询用户空间fifo的开销,我们对驱动程序进行了一次非常简单的read()调用,实际上它只是在FIFO中有任何数据时才会被挂起(没有任何内容真正“读入”到read()调用中提供的缓冲区.然后,此read()调用返回,并且线程继续从fifo读取数据,直到它为空,然后通过调用伪read()调用再次挂起.
通过在检测到帧丢失之前可以传输多少网络流来测量该系统是非常有效的.但我们已经确定使用假的read()调用会导致Linux“top”实用程序报告我们的应用程序的大量CPU使用情况.
我们已经构建了2个版本的应用程序 – 一个操作如上,另一个是相同的,除了它从不调用假读取(),而是通过介入的usleep()调用轮询fifo.当我们查看“top”报告的CPU使用情况时,对于2个情况,当每个发送5个流时,我们得到:
1)read()版本:CPU 12%
2)usleep()版本:CPU 4%
当然,现实中的轮询效率较低,如果我们忽略“顶级”所说的内容,而只是测量两个版本在我们看到帧丢失之前可以传输多少个同时网络流,那么上面的版本1获胜.
我们已经验证上面的read()调用是否正常运行.如果某个bug导致read()调用立即返回,即使fifo中没有数据,那么该线程最终会进行昂贵的连续轮询.但这种情况并非如此; read()调用使线程每秒正好运行30次.
我们认为我们的玩具busybox版本的“top”可能会有一些快捷方式 – 但是这些结果都没有在/ proc // stat中的原始数字中用于计算其显示的数字.
这个问题必须限制Linux内核本身如何收集/ proc // stat中显示的数字.
如果有人理解为什么会这样,请指出我正确的方向.
谢谢!
最佳答案 我可以保证,顶部不是骗你的.如果它说您的进程使用了12%的CPU,则它使用12%的CPU.这没有两种方法.
显然,调用usleep不会花费太多时间,因为它会导致进程暂停(至少)所请求的时间.这可能是每次睡眠呼叫100个周期.阅读远不止于此,所以我并不感到意外需要更多的CPU时间 – 特别是如果你做了很多.
阅读将:
>检查您的句柄是否有效.
>检查缓冲区指针和长度是否有效.
>将长度从用户空间复制到内核空间.
>将读取的数据插入合适的数据结构中.
>查找相关句柄以及发出请求的驱动程序.
>向您的驱动程序发出读取请求.
>驱动程序睡眠过程[假设没有可用数据].
>当有可用数据时,驱动程序会唤醒进程.
>将读取长度数据复制到用户空间.
>回到来电者.
与usleep相比:
>去睡觉吧.
>醒来.
>返回用户.
腐败“去睡觉”不是一个单一的琐碎功能,醒来也不是微不足道的.但它们是相同的操作,在睡眠期间,该过程不使用CPU.
您可以通过从/ dev / zero读取并在其间进行睡眠来轻松计算出读取的开销. / dev / zero是一个立即返回填充零的缓冲区的设备.
或者,您可以尝试使用oprofile之类的功能进行性能分析,并查看花费的时间.
但我很确定你的上衣不会撒谎.