如何找出阻止Linux任务安排的原因?

时间:2014-05-07 09:09:03

标签: multithreading debugging linux-kernel scheduling

我有一个带有多个单线程用户进程的嵌入式Linux系统。其中一个定期(非常偶尔)无法安排,即使有工作等待它。如何找出阻止进程(任务/线程)被安排的内容?

我已经使用strace -p <pid>跟踪进程的内核调用,当它挂起时,得到了这个:

...
ioctl(13, 0x40104604, 0xffff6ecf08)     = 0
_newselect(13, [8 9 10 11 12], [], [], {0, 0}) = 0 (Timeout)
_newselect(13, [8 9 10 11 12], [], [], {0, 0}) = 0 (Timeout)
_newselect(13, [8 9 10 11 12], [], [], {0, 15000}) = 0 (Timeout)
_newselect(13, [8 9 10 11 12], [], [], {0, 19000}) = 1 (in [12], left {0, 705})
read(12, "\3$GPZDA,072522.038,06,01,1980,,*"..., 1600) = 32
_newselect(13, [8 9 10 11 12], [], [], {0, 0}) = 0 (Timeout)
_newselect(13, [8 9 10 11 12], [], [], {0, 0}) = 0 (Timeout)
_newselect(13, [8 9 10 11 12], [], [], {0, 15000}

在15ms超时后,最后一次select()调用(strace输出中的_newselect())没有返回。似乎在select中发生了一个上下文切换,之后任务不再运行很长时间(几十秒)。当任务最终恢复时,它会再次正常运行。

我在启用了ftrace的情况下重建了内核,并启用了sched_switch跟踪器,并在进程恢复时获得了此输出:

...
<idle>-0     [000] 10876.339906:      0:120:R   + [000]  1385:120:R ems
<idle>-0     [000] 10876.339915:      0:120:R ==> [000]  1385:120:R ems
   ems-1385  [000] 10876.340006:   1385:120:S ==> [000]     0:120:R <idle>
<idle>-0     [000] 10876.340300:      0:120:R ==> [000]  1379:100:R gps
   gps-1379  [000] 10876.340453:   1379:100:R   + [000]  1377:120:R dgs
...

感兴趣的过程是gps(pid 1379),它在37秒的不活动时间后在倒数第二行重新开始。 (在过程本身的调试printfs中可以知道不活动的延迟。)请注意,没有&#39; +&#39;表示该任务刚刚准备就绪的行 - 我假设这发生在37秒前(当然迹线不会那么远!)。相反,任务刚刚开始运行,没有任何迹象表明它为什么被阻止。

我尝试使用setpriority(PRIO_PROCESS, <pid>, -20)在发生挂断几秒钟后从另一个进程提升任务的优先级(这就是上述跟踪中优先级显示为100的原因) ,而不是默认的120),但没有区别,所以我不相信这个问题与优先权有关。

我现在可以做些什么来找出导致任务暂停的原因?我对内核空间的调试并不熟悉 - ftrace套件中是否还有其他工具可以在单个pid上运行以查看它在做什么?任何其他内核调试工具?我可以识别问题何时发生,但仅在几秒钟过后 - 所以我可以在那时触发或停止任何数据捕获,但追踪发生的事件比那段时间更早是棘手的。

内核是版本2.6.33,如果有帮助的话。由于各种原因,升级到更高版本并不是一个实际的主张。

非常欢迎任何有关如何进一步调试的建议或建议!

0 个答案:

没有答案