diff --git a/study/kernel/01-process/05-schedule/03-design/01-design/README.md b/study/kernel/01-process/05-schedule/03-design/01-design/README.md index d19b7c4..e556fb7 100644 --- a/study/kernel/01-process/05-schedule/03-design/01-design/README.md +++ b/study/kernel/01-process/05-schedule/03-design/01-design/README.md @@ -89,6 +89,63 @@ linux把进程区分为实时进程和非实时进程, 其中非实时进程进 并且每个调度器包括两个内容:**调度框架**(其实质就是两个函数框架)及**调度器类** +**抢占标识TIF_NEED_RESCHED** +内核在检查need_resched标识TIF_NEED_RESCHED的值判断是否需要抢占当前进程, 内核在thread_info的flag中设置了一个标识来标志进程是否需要重新调度, 即重新调度need_resched标识TIF_NEED_RESCHED, 内核在即将返回用户空间时会检查标识TIF_NEED_RESCHED标志进程是否需要重新调度 + +**周期调度器** + +周期性调度器scheduler_tick由内核时钟中断周期性的触发, 周期性调度器以固定的频率激活负责当前进程调度类的周期性调度方法, 以保证系统的并发性, 周期性调度器通过调用进程所属调度器类的task_tick操作完成周期性调度的通知和配置工作, 通过resched_curr函数(早期的resched_task函数)设置抢占标识TIF_NEED_RESCHED来通知内核在必要的时间由主调度函数完成真正的调度工作, 此种做法称之为延迟调度策略 + +>关于周期性调度器的详细信息, 参见[Linux核心调度器之周期性调度器scheduler_tick--Linux进程的管理与调度(十八)](http://blog.csdn.net/gatieme/article/details/51872561) + +**主调度器** + +schedule就是主调度器的工作函数, 在内核中的许多地方, 如果要将CPU分配给与当前活动进程不同的另一个进程, 都会直接调用主调度器函数schedule或者其子函数__schedule. + +**__schedule完成抢占** + +* 完成一些必要的检查, 并设置进程状态, 处理进程所在的就绪队列 + +* 调度全局的pick_next_task选择抢占的进程 + + 如果当前cpu上所有的进程都是cfs调度的普通非实时进程, 则直接用cfs调度, 如果无程序可调度则调度idle进程 + + 否则从优先级最高的调度器类sched_class_highest(目前是stop_sched_class)开始依次遍历所有调度器类的pick_next_task函数, 选择最优的那个进程执行 + +* context_switch完成进程上下文切换 + + 调用switch_mm(), 把虚拟内存从一个进程映射切换到新进程中 + + 调用switch_to(),从上一个进程的处理器状态切换到新进程的处理器状态。这包括保存、恢复栈信息和寄存器信息 + +>主调度器的详细信息, 可以参考 [Linux进程核心调度器之主调度器--Linux进程的管理与调度(十九)](http://blog.csdn.net/gatieme/article/details/51872594) + + + + + +**内核抢占和用户抢占** + +而根据进程抢占发生的时机, 抢占可以分为内核抢占和用户抢占, **内核抢占**就是指一个在内核态运行的进程, 可能在执行内核函数期间被另一个进程取 + +一般来说,用户抢占发生几下情况: + +* 从系统调用返回用户空间; + +* 从中断(异常)处理程序返回用户空间 + +内核抢占发生的时机,一般发生在: + +* 当从中断处理程序正在执行,且返回内核空间之前。当一个中断处理例程退出,在返回到内核态时(kernel-space)。这是隐式的调用schedule()函数,当前任务没有主动放弃CPU使用权,而是被剥夺了CPU使用权。 + +* 当内核代码再一次具有可抢占性的时候,如解锁(spin_unlock_bh)及使能软中断(local_bh_enable)等, 此时当kernel code从不可抢占状态变为可抢占状态时(preemptible again)。也就是preempt_count从正整数变为0时。这也是隐式的调用schedule()函数 + +* 如果内核中的任务显式的调用schedule(), 任务主动放弃CPU使用权 + +* 如果内核中的任务阻塞(这同样也会导致调用schedule()), 导致需要调用schedule()函数。任务主动放弃CPU使用权 + + +>详细内容请参见 [Linux用户抢占和内核抢占详解(概念, 实现和触发时机)--Linux进程的管理与调度(二十)](http://blog.csdn.net/gatieme/article/details/51872618) ##2.2 6种调度策略 ------- @@ -301,11 +358,15 @@ linux2.6内核将任务优先级进行了一个划分, 实时优先级范围是0 ``` + | 优先级范围 | 描述 | | ------------- |:-------------:| | 0——99 | 实时进程 | | 100——139 | 非实时进程 | +关于优先级的详细信息可以参见[ Linux进程优先级的处理--Linux进程的管理与调度(二十二)](http://blog.csdn.net/gatieme/article/details/51719208) + + ###3.1.2 调度策略 ------- @@ -1406,4 +1467,4 @@ linux下被调度的不只是进程, 还可以是进程组. 因此需要一种 | rq |cfs_rq | rt_rq, dl_rq | - +#