Linux内核分析-9/进程的调度时机

时间:2022-09-25 15:46:12

Linux内核分析-9/进程的调度时机

  • 上篇博客已经讲了调度的路径
  • 明白了
  • 1/调度都是在内核中间进行的,调用调度函数的函数A都是在内核态
  • 2/调用调度函数的函数A都是由两个路径
    • 1/用户态陷入内核态,调用 调度 (时机根据内核版本不同而不同,但都是在内核态调用)
    • 2/因为中断,进入中断处理函数,调用 调度 (中断处理函数在内核态中)

linux-0.11中的调度时机

  • linux-0.11中调用 schedule 函数的次数 屈指可数,总共8次
//次数 1 : do_timer(timer_interrupt->do_timer)
这个函数在时钟中断函数中被调用的, 函数 do_timer 直接调用了 schedule
//次数 2 : release
这个函数是 在exit 和wait uname 的 底层路径 中调用的 ,函数 release 直接调用了 release
//次数 3 : do_exit
这个函数是 被 exit 和 signal do_no_page(页异常中断处理函数) 和其他系统调用 调用的 .
//次数 4 : sys_waitpid
这个函数是被 waitpid 调用的
//次数 5 : sys_pause
这个函数是被 pause 调用的
//次数 6 : sleep_on
这个函数 是被 sync dev open mount setup mkdir read umount execv 调用
//次数 7 : interruptible_sleep_on
这个函数是 不可中断的睡眠,相对于 sleep_on(可中断) 来说用的地方要少 ,被 open mount setup write read 调用
//次数 8 : tty_write
这个函数的调用路径 tty_write(sys_write->rw_char->crw_table->rw_tty->rw_ttyx->tty_write- 写阻塞 ->schedule)
  • 从上面可以看到,linux-0.11中的调用时机只有两种:
    • 1.在系统调用路径中
    • 2.在中断处理函数路径中

linux的调度时机

  • 可见linux-0.11中的调度时机分为两种,一种是系统调用,一种是中断处理函数,但归结起来,都是中断引起的.
  • 不过一个是软中断,一个是硬中断
  • 但是后来的东西怎么变了呢?哪里变了呢?CHANGELOG
    • 分类变了,但还是哪两种?现在被称呼为主动调度 和被动调度
    • 1.主动调度就是之前的系统调用.
    • 2.被动调度还是之前的中断处理和部分系统调用(都走 ret_from_sys_call ),不过这次不是在中断处理过程中调用的 schedule 函数,而是在中断处理函数返回之后,进入用户态之前(即 ret_from_sys_call 之后)根据 进程调度标志 need_resched 调用的.
    • 3.另外linux-2.6之前的内核只支持从用户态开始的的调度,不支持从内核态的调度.如果在内核态下,发生调度什么的,只能先出内核态(即到达用户态),再陷入内核态做调度,这样增加了消耗(内核态->用户态->内核态 的 过程).内核态的抢占是通过 ( ret_from_sys_call ) 后的 preempt_schedule_irq 进行的
    • 要细分的话可以分为很多种,请看下面的分类
1/主动调度
1.1/正在执行的进程执行完毕。 例如 exit
1.2/正在执行的进程发出IO请求。例如 read
1.3/正在执行的进程要等待其他进程或系统发出的事情时。 wait
1.4/ 正在执行的进程中那是得不到所要的系统资源。 pthread_mutex_lock
2/被动调度(都是在ret_from_sys_call中被调用的,通过检测 need_resched )
2.1/当中断处理程序处理完中断 IO中断
2.2/进程释放独占资源 pthread_mutex_unlock
2.3/某进程发“发送消息”系统调用 signal
2.4/其他任何原因引起有进程从其他状态变成就绪状态 //进程被中调选中时
3/没有新就绪进程,但原进程时间片到或优先级发生变化。
3.1/时钟中断函数中的 调用 调度
3.2/系统调用改变进程的优先级变化后的 调度
//什么时候需要调度?为什么?
//什么地方会调度?代码中
Linux的进程调度时机与现代操作系统中的调度时机基本一致,为了判断是否可以执行内核的进程调度程序来调度进程,Linux中设置了进程调度标志 need_resched ,当标志为1时,可执行调度程序.
通常,Linux调度时机分以下两种情况:
(1)主动调度:指显式调用schedule()函数明确释放CPU,引起新一轮调度.一般发生在当前进程状态改变,如:进程终止、进程睡眠、进程对某些信号处理过程中等.
(2)被动调度:指不显示调用schedule()函数,只是PCB中的 need_resched 进程调度标志,该域置位为1将引起新的进程调度,而每当中断处理和系统调用返回时,核心调度程序都会主动查询need_resched的状态(若置位,则主动调用 schedule ()函数。一般发生在新的进程产生时、某个进程优先级改变时、某个进程等待的资源可用被唤醒时、当前进程时间片用完等.
  1、进程状态转换的时刻:进程终止、进程睡眠;
  2、当前进程的时间片用完时(current->counter=0);
  3、设备驱动程序
  4、进程从中断、异常及系统调用返回到用户态时;
void resched_task(struct task_struct *p)
{
int cpu;

assert_raw_spin_locked(&task_rq(p)->lock);

if (test_tsk_need_resched(p))
return;

set_tsk_need_resched(p);

cpu = task_cpu(p);
if (cpu == smp_processor_id())
return;

/* NEED_RESCHED must be visible before we test polling */
smp_mb();
if (!tsk_is_polling(p))
smp_send_reschedule(cpu);
}

Linux内核分析-9/进程的调度时机

Linux内核分析-9/进程的调度时机


资料

linux调度器源码分析 - 概述(一)

need_resched 是怎么使用的(ZT)

调度时机分析之被动调度(之内核态抢占调度)

进程调度的时机与进程的切换

深入分析linux调度机制
Linux进程调度机制