我有一个带有多个单线程用户进程的嵌入式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,如果有帮助的话。由于各种原因,升级到更高版本并不是一个实际的主张。
非常欢迎任何有关如何进一步调试的建议或建议!