1、hungtask D状态
hungtask D状态定位思路:
1、用户态和底层驱动交互,比如IO交互,一般是等待硬件响应。
2、死锁,mutex lock等;
3、竞争激烈,导致120s都无法拿到资源,比如内存耗尽或大内核锁;
iowait/io_schedule
https://zhuanlan.zhihu.com/p/31690737
hungtask超时调用栈中存在io_schedule
void io_schedule(void)
{
int token;
token = io_schedule_prepare();
schedule();
io_schedule_finish(token);
}
int io_schedule_prepare(void)
{
int old_iowait = current->in_iowait;
current->in_iowait = 1;
blk_schedule_flush_plug(current);
return old_iowait;
}
void io_schedule_finish(int token)
{
current->in_iowait = token;
}
当task发生iowait的时候,内核对他们的处理方法是将task切换出去,让可运行的task先运行,而在切换出去前,会将其in_iowait设置为1,再次被唤醒的时候in_iowait被设置为原值。
相关函数io_schedule,io_schedule_timeout,mutex_lock_io,mutex_lock_io_nested。
以上函数都会设置task运行状态TASK_UNINTERRUPTIBLE
schedule
schedule函数完成如下工作:
1、确定当前就绪队列, 并在保存一个指向当前(仍然)活动进程的task_struct指针
2、检查死锁, 关闭内核抢占后调用__schedule完成内核调度
3、恢复内核抢占, 然后检查当前进程是否设置了重调度标志TLF_NEDD_RESCHED, 如果该进程被其他进程设置了TIF_NEED_RESCHED标志, 则函数重新执行进行调度
asmlinkage __visible void __sched schedule(void)
{
/* 获取当前的进程 */
struct task_struct *tsk = current;
/* 避免死锁 */
sched_submit_work(tsk);
do {
preempt_disable(); /* 关闭内核抢占 */
__schedule(false); /* 完成调度 */
sched_preempt_enable_no_resched(); /* 开启内核抢占 */
} while (need_resched()); /* 如果该进程被其他进程设置了TIF_NEED_RESCHED标志,则函数重新执行进行调度 */
}
EXPORT_SYMBOL(schedule);
2、调测运维
kbox,kdump,sysmonitor,sar
3、软锁问题
cpu长时间不能被调度导致softlockup
https://www.ctyun.cn/developer/article/354108173819973