用户空间IO操作期间的线程延迟

我正在使用embedded式Linux内核开展项目,在访问闪存时遇到了线程延迟的问题。

我的应用程序是multithreading的,一些线程必须在小于500毫秒内完成给定的任务。 问题是,这些线程有时在1秒钟内“冻结”,我的500毫秒的执行时间很好。

这种行为似乎与闪存写入有关,因为当我从shell执行“dd”命令以连续写入闪存时,这种行为也会发生。

我尝试了各种configuration:

  • 增加了我的实时线程的优先级:SCHED_RR,priority = 55
  • 更改了IO调度程序:deadline => cfq(更好:在15分钟而不是3分钟后发生故障)。

通过使用ftrace工具,我可以看到,在“冻结”时间内,一些线程和进程仍在运行,在其他任务(空闲任务时隙持续时间> 20ms)之间有很多“空闲”任务时间:

  • 2个networking线程(SCHED_RR,优先级= 50)
  • dd进程

我不明白:

  • 为什么所有其他任务在所有这段时间都被“locking”(有时在请求互斥时,有时在计算一个简单的16位CRC时)。
  • 为什么在这段时间内ftrace(调度事件之间)可以看到这么多的空闲时间。
  • 为什么更高的应用程序线程优先级不能解决问题。

我怀疑是和内核中的IOpipe理有关的东西,好像内核抢占了每个非IO线程,以完成所有与IO(networking,文件,…)有关的工作。

有没有人有什么可能会导致这种延迟的想法?

我的内核设置:

  • Linux内核版本2.6.39
  • 抢先选项启用
  • 滴答
  • HZ = 1000
  • CFQ调度程序(默认设置)

编辑:

由于我不是专家,我与你分享ftrace capture(用kernelshark查看): https ://drive.google.com/file/d/0B6pJb20-D0D2NHZBUHJVRlV0aDg/view ? usp = sharing

也许它可以帮助你看到我的系统上真正发生了什么。

在这个捕获中,我用外部的“dd”命令重现了我在名义条件下遇到的类似的行为。

“洞”(“冻结”)是(在我的应用程序没有更多的自定义ftrace标记)在时间戳:

  • 开始:469.118370
  • 结束:469.802940

另一个小“洞”

  • 开始:469.807644
  • 结束:469.952975

我认为这可能是因为内核已经决定它必须刷新一些文件系统的元数据,或者做其他的文件系统管理,并且必须拖延你的进程,直到它做得足够。

我有类似的问题,并使用多线程和用户级缓冲区吸收摊位。 看到我的老问题,并在这里回答 。

我更新了这个主题的状态:我们认为我们找到了锁的根本原因。

我的公司雇了一个Linux专家2天。

感谢他,我们发现:

这些锁是由内核完成数据刷新时所有闪存访问都被阻塞的事实引起的。

特别是我们的记录器模块(用于时间戳…),它调用syslog()函数。

但是这个syslog()函数也阻塞了这个进程,即使syslogd守护进程是访问flash的真实进程…(我们怀疑用于syslog通信的unix套接字直到资源可用时才会阻塞,就像在编写bash pipe'|'时写很多日志到位于闪存中的文件)。

解决方法是将实时线程与其他线程之间的所有访问权限分开,通过将日志/闪存访问权限分隔成一个独立的线程(使用非阻塞自定义消息队列作为通信项目)

而且它似乎有效!

我以前没有读过blueshift答案,但似乎他是正确的;-)