我正在编写一个小应用程序,它以恒定的速率在 SD 卡上写入 jpeg 图像。 我选择了 EXT3 文件系统,但在 EXT2 文件系统中观察到相同的行为。
我的写作循环看起来像这样:
get_image()
fwrite()
fsync()
或者像这样:
get_image()
fopen()
fwrite()
fsync()
fclose()
我还显示了一些计时统计信息,我可以看到我的程序有时会被阻塞几秒钟。 平均速率还是不错的,因为如果我将传入的图像保存在一个 fifo 中,那么在这样的停顿之后我会在短时间内写入很多图像。你知道这是操作系统的问题还是与SD卡本身有关? 我怎样才能更接近实时?我不需要很强的实时性,但停顿几秒钟是 Not Acceptable 。
一些精度: 是的,有必要在每个文件之后进行 fsync,因为我希望图像在磁盘上,而不是在某些用户或内核缓冲区中。没有fsyncing,我有更好的throughoutput, 但仍然无法接受的摊位。我不认为这是缓冲区问题,因为第一个停顿发生在写入 50 MB 之后。根据手册页,fsync 在这里正是为了确保没有数据被缓冲。
关于平均写入速率的精度: 我正在以我使用的卡可持续的速度写作。如果我在等待 fsync 完成时堆积传入的图像,那么在这个停顿之后写入传输速率将增加,我将很快回到平均速率。 平均传输速率约为 1.4 MBytes/s。
系统是一台运行 ubuntu 8.04 和 stock kee (2.6.24.19) 的现代笔记本电脑
最佳答案
尝试使用O_DIRECT
打开文件并在应用程序级别进行缓存。
我们在 STB Box 中实现 PVR(个人视频记录)功能时遇到了类似的问题。 O_DIRECT
技巧最终满足了我们的需求。(*)
没有O_DIRECT
。 write()
的数据会先缓存在内核缓冲区中,然后在调用fsync
或内核缓存缓冲区已满时刷新到媒体。(* *).
使用 O_DIRECT
。内核将直接对用户空间缓冲区指向的物理内存执行 DMA,该缓冲区作为参数传递给 write
系统调用。因此,在用户空间内存和内核缓存之间的副本中不会花费 CPU 和内存带宽,并且在缓存管理(如缓存查找、每页锁等)中不会在内核中花费 CPU 时间。 (从 here 复制)
不确定它是否也能解决您的问题,但您可能想尝试一下。
*尽管 Linus 的 critize O_DIRECT
,它确实解决了我们的问题。
** 假设您没有使用 O_DSYNC
或 O_SYNC
打开文件
关于linux - SD卡写入性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/191984/