我们之前有分析过,update_process_times会判断当前进程的时间片是否用完,如果用完了会设置TIF_NEED_RESCHED,在合适的时机,调用schedule函数做实际的进程调度。
进程调度的时机,主要分成以下四种:
- 直接调用schedule
- 间接调用schedule,如果msleep函数
- 中断返回时检测TIF_NEED_RESCHED,如果设置则调用schedule
- 系统调用返回用户空间的时候检测TIF_NEED_RESCHED,如果设置该标记,则调用schedule。
直接调用schedule没什么可说的,下面主要分析后面四种调度时机的代码。
间接调用schedule
void msleep(unsigned int msecs)
{
unsigned long timeout = msecs_to_jiffies(msecs) + 1;
while (timeout)
timeout = schedule_timeout_uninterruptible(timeout);
}
首先计算超时时间,并调用 schedule_timeout_uninterruptible函数,该函数返回剩余的超时时间。
signed long __sched schedule_timeout_uninterruptible(signed long timeout)
{
__set_current_state(TASK_UNINTERRUPTIBLE);
return schedule_timeout(timeout);
}
首先设置当前进程的状态为TASK_UNINTERRUPTIBLE,然后调用 schedule_timeout。
signed long __sched schedule_timeout(signed long timeout)
{
struct timer_list timer;
unsigned long expire;
switch (timeout)
{
case MAX_SCHEDULE_TIMEOUT:
/*
* These two special cases are useful to be comfortable
* in the caller. Nothing more. We could take
* MAX_SCHEDULE_TIMEOUT from one of the negative value
* but I' d like to return a valid offset (>=0) to allow
* the caller to do everything it want with the retval.
*/
schedule();
goto out;
default:
/*
* Another bit of PARANOID. Note that the retval will be
* 0 since no piece of kernel is supposed to do a check
* for a negative retval of schedule