record-8.常见类型问题

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

你可能感兴趣的:(linux)