• linux进程调度


    schedule调度流程

          schedule就是主调度器的函数, 在内核中如果要将CPU分配给与当前活动进程不同的另一个进程, 都会直接调用主调度器函数schedule, 

    该函数完成如下工作:

    1. 确定当前就绪队列, 并在保存一个指向当前(仍然)活动进程的task_struct指针。
    2. 检查死锁, 关闭内核抢占后调用__schedule完成内核调度。

    3. 恢复内核抢占, 然后检查当前进程是否设置了重调度标志TLF_NEDD_RESCHED, 如果该进程被其他进程设置了TIF_NEED_RESCHED标志, 则函数重新执行进行调度。

    do {
            preempt_disable();                                  /*  关闭内核抢占  */
            __schedule(false);                                  /*  完成调度  */
            sched_preempt_enable_no_resched();                  /*  开启内核抢占  */
        } while (need_resched());   /*  如果该进程被其他进程设置了TIF_NEED_RESCHED标志,则函数重新执行进行调度    */

    __schedule如何完成内核抢占

           查看__schedule 函数实现,主要做如下工作:

    1. 完成一些必要的检查, 并设置进程状态, 处理进程所在的就绪队列。

    2. 调度全局的pick_next_task选择抢占的进程。

      • 如果当前cpu上所有的进程都是cfs调度的普通非实时进程, 则直接用cfs调度, 如果无程序可调度则调度idle进程。

      • 否则从优先级最高的调度器类sched_class_highest(目前是stop_sched_class)开始依次遍历所有调度器类的pick_next_task函数, 选择最优的那个进程执行。

    3. context_switch完成进程上下文切换。

      • 调用switch_mm(), 把虚拟内存从一个进程映射切换到新进程中。

      • 调用switch_to(),从上一个进程的处理器状态切换到新进程的处理器状态。这包括保存、恢复栈信息和寄存器信息。

    调度的内核抢占和用户抢占

          内核在完成调度的过程中总是先关闭内核抢占, 等待内核完成调度的工作后, 再把内核抢占开启, 如果在内核完成调度器过程中, 这时候如果发生了内核抢占,我们的调度会被中断, 而调度却还没有完成, 这样会丢失我们调度的信息。

          在调度完成后, 内核会去判断need_resched条件, 如果这个时候为真, 内核会重新进程一次调度,此次调度由于发生在内核态因此仍然是一次内核抢占need_resched条件其实是判断need_resched标识TIF_NEED_RESCHED的值,内核在thread_info的flag中设置了一个标识来标志进程是否需要重新调度, 即重新调度need_resched标识TIF_NEED_RESCHED,内核在即将返回用户空间时会检查标识TIF_NEED_RESCHED标志进程是否需要重新调度,如果设置了,就会发生调度, 这被称为用户抢占,

          而内核抢占是通过自旋锁preempt_count实现的, 同样当内核可以进行内核抢占的时候(比如从中断处理程序返回内核空间或内核中的进程被堵塞的时候),内核会检查preempt_count和TIF_NEED_RESCHED标志,如果进程设置了 TIF_NEED_RESCHED标志,并且preempt_count为0,则发生内核抢占。

  • 相关阅读:
    软工5--结对2--四则运算生成器
    软工4——结对审查
    天数计算器
    翻转字符串
    位图排序
    软工 assignment 3 —— 求最大子数列之和
    剑指offer 面试题5.替换空格
    剑指offer 面试题4.二维数组中的查找
    剑指offer 面试题3.数组中重复的数字
    如何通过onenote发送博客到cnblog(博客园)
  • 原文地址:https://www.cnblogs.com/jerry116/p/8811253.html
Copyright © 2020-2023  润新知