首页 文章

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

提问于
浏览
7

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

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

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

我尝试了各种配置:

  • 增加了我的实时线程的优先级:SCHED_RR,priority = 55

  • 更改了IO调度程序:deadline => cfq(更好:15分钟后失败而不是3分钟) .

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

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

  • dd进程

我不明白:

  • 为什么所有其他任务在所有这些时间内都是"locked"(有时在请求互斥锁时,有时在计算简单的16位-CRC时) .

  • 为什么在此期间使用ftrace(在sched事件之间)可以看到如此多的空闲时间 .

  • 为什么更高的应用程序线程优先级无法解决问题 .

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

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

我的内核设置:

  • Linux内核版本2.6.39

  • 启用了Preempt选项

  • 无所事事

  • 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

2 回答

  • 2

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

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

  • -1

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

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

    多亏了他,我们发现:

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

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

    但是这个syslog()函数也阻塞了进程,即使syslogd守护进程是访问flash的真正进程...(我们怀疑用于syslog通信的unix套接字阻塞,直到资源可用,比如写入时的bash管道'|'很多日志都记录在flash中的文件中 .

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

    它似乎有效!

    我之前没有读过blueshift的答案,但似乎他是对的;-)

相关问题