6、抢占和上下文切换
上下文切换:从一个可执行进程切换到另一个可执行进程。相关函数会进行如下两步操作:
- 将虚拟内存从上一个进程映射切换到新进程中
- 从上一个进程的处理器状态切换到新进程的处理器状态
内核提供了一个need_resched标志来表明是否需要重新执行一次调度,而不仅是靠用户程序代码显式地调用schedule()。每个进程都包含一个need_resched标志,这是因为访问进程描述符内的数值要比访问全局变量快。
6.1 用户抢占
用户抢占在以下情况时发生:
- 从内核系统调用返回用户空间时
- 从中断处理程序返回用户空间时
这两种情况下,内核都会检查need_resched标志,若被设置,则会导致schedule()被调用,选择一个其他(更合适的)进程投入运行,从而发生用户抢占。
6.2 内核抢占
Linux完整地支持内核抢占。只要重新调度是安全的,内核就可以在任何时间抢占正在执行的任务。
何时重新调度是安全的:只要没有持有锁,内核就可以进行抢占。锁是非抢占区域的标志。
内核抢占在以下情况时发生:
- 中断处理程序正在执行,且返回内核空间之前
- 内核代码再一次具有可抢占性的时候(没有锁)
- 内核中的任务显式地调用schedule()
- 内核中的任务阻塞(这同样会导致调用shcedule())
7、实时调度策略
Linux提供了两种实时调度策略:SCHED_FIFO和SCHED_RR
普通的、非实时调度策略:SCHED_NORMAL
实时策略并不被完全公平调度器来管理,而是被一个特殊的实时调度器管理。
两种实时调度算法实现的都是静态优先级。内核不为实时进程计算动态优先级。Linux的试试调度算法提供了一种软实时工作方式。
实时优先级范围从0到MAX_RT_PRIO减1。默认情况下,MAX_RT_PRIO为100——所以默认的实时优先级范围是0~99 。
SCHED_NORMAL级进程的nice值共享了这个取值范围,它的取值范围是MAX_RT_PRIO到MAX_RT_PRIO+40。即在默认情况下,非实时进程的nice值从-20 ~ +19直接对应的是从100 ~ 139的实时优先级范围。所以,实时优先级与普通nice值范围并无交集,且实时优先级总是高于普通nice值优先级