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

时间:2015-03-18 16:08:57

标签: linux multithreading linux-kernel embedded-linux scheduling

我正在使用嵌入式Linux内核开展项目,并且在访问闪存时遇到线程延迟问题。

我的应用程序是多线程的,有些线程必须在不到500毫秒的时间内完成给定的任务。问题是这些线程有时会在超过1秒的时间内被“冻结”,而我的500毫秒执行时间会被延长。

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

我尝试了各种配置:

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

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

  • 2个网络线程(SCHED_RR,优先级= 50)
  • dd process

我不明白:

  • 为什么所有其他任务在所有这些时间都被“锁定”(有时候 在请求互斥时,有时在进行简单的计算时 16位-CRC)。
  • 为什么在此期间使用ftrace(在sched事件之间)可以看到如此多的空闲时间。
  • 为什么更高的应用程序线程优先级无法解决问题。

我怀疑与内核中的IO管理有关的东西,好像内核抢占了每个非IO线程,以便完成与IO相关的所有工作(网络,文件......)。

有没有人知道可能导致这种延迟的原因?

我的内核设置:

  • 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
  • end:469.802940

另一个小“洞”

  • 开始:469.807644
  • end:469.952975

2 个答案:

答案 0 :(得分:2)

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

我遇到了类似的问题,并使用多线程和用户空间缓冲来吸收停顿。请参阅my old question and answer here

答案 1 :(得分:-1)

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

我公司聘请了一位Linux专家2天。

感谢他,我们发现:

锁是由内核完成数据刷新时所有闪存访问被阻止引起的。

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

但是这个syslog()函数也会阻塞进程,即使syslogd守护进程是访问flash的真正进程... (我们怀疑用于syslog通信的unix套接字阻塞,直到资源可用,比如bash管道' |'当将大量日志写入闪存中的文件时)。

解决方案是通过对隔离线程进行日志/闪存访问(使用非阻塞自定义消息队列作为通信项目),在实时线程和另一个线程之间拆分对闪存的所有访问权限。

似乎它有效!

我之前没有读过蓝调回答,但似乎他是对的; - )