Linux 进程管理之进程调度与切换

进程调度相关内核结构我们知道,进程运行需要各种各样的系统资源,如内存、文件、打印机和最宝贵的 CPU 等,所以说,调度的实质就是资源的分配 。系统通过不同的调度算法(Scheduling Algorithm)来实现这种资源的分配 。通常来说,选择什么样的调度算法取决于资源分配的策略(Scheduling Policy) 。
有关调度相关的结构保存在 task_struct 中,如下:
struct task_struct {/*task_struct 采用了如下3个成员表示进程的优先级,prio、normal_prio表示动态优先级static_prio 为静态优先级,静态优先级是进程启动时分配的优先级,它可以使用nice和sched_setscheduler系统调用修改,否则在进程运行期间会一直保持恒定*/int prio, static_prio, normal_prio;/*sched_clas表示该进程所属的调度器类2.6.24版本中有3中调度类:实时调度器 : rt_sched_class完全公平调度器:fair_sched_class空闲调度器: idle_sched_class*/const struct sched_class *sched_clas;//调度实体struct sched_entity se;/*policy 保存了对该进程应用的调度策略 。进程的调度策略有6种SCHED_NORMAL SCHED_FIFO SCHED_RR SCHED_BATCH SCHED_IDLE普通进程调度策略: SCHED_NORMAL、SCHED_BATCH、SCHED_IDLE,这些都是通过完全公平调度器来处理的实时进程调度策略: SCHED_RR、SCHED_FIFO 这些都是通过实时调度器来处理的*/unsigned int policy;/*除了内核线程(Kernel Thread),每个进程都拥有自己的地址空间(也叫虚拟空间),用mm_struct 来描述 。active_mm是为内核线程而引入的 。因为内核线程没有自己的地址空间,为了让内核线程与普通进程具有统一的上下文切换方式,当内核线程进行上下文切换时,让切换进来的线程的active_mm指向刚被调度出去的进程的active_mm(如果进程的mm 域不为空,则其active_mm 域与mm 域相同)*/struct mm_struct *mm, *active_mm;//表示实时进程的优先级,最低的优先级为0,最高为99,值越大,优先级越高unsigned int rt_priority;...};每个进程都拥有自己的地址空间(也叫虚拟空间),用 mm_struct 来描述 。
active_mm 是为内核线程而引入的,因为内核线程没有自己的地址空间,为了让内核线程与普通进程具有统一的上下文切换方式,当内核线程进行上下文切换时,让切换进来的线程的 active_mm 指向刚被调度出去的进程的 active_mm(如果进程的mm 域不为空,则其 active_mm 域与 mm 域相同) 。

Linux 进程管理之进程调度与切换

文章插图
在 linux 2.6 中 sched_class 表示该进程所属的调度器类有3种:
  • 实时调度器 (RT,rt_sched_class) : 为每个优先级维护一个队列;
  • 完全公平调度器 (CFS,fair_sched_class) : 采用完全公平调度算法,引入虚拟运行时间的概念 。
  • 空闲调度器(idle_sched_class) : 为每个 CPU 都会有一个 idle 线程,当没有其他进程可以调度时,调度运行idle线程 。
进程的调度策略有5种,用户可以调用调度器里不同的调度策略:
  • SCHED_FIFO :采用了先入先出,不使用时间片的调度算法 。若处于可执行状态,就会一直执行,没有更高优先级的情况下,进程只能等待其主动让出 cpu;
  • SCHED_RR :时间片轮转,进程用完时间片后加入优先级对应的运行队列的尾部,把 CPU 让给同一优先级的其他进程;
  • SCHED_NORMAL : 使 task 选择 CFS 调度器来调度运行;
  • SCHED_BATCH:批量处理,使 task 选择 CFS 调度器来调度运行;
  • SCHED_IDLE: 使 task 选择 CFS 调度器来调度运行

Linux 进程管理之进程调度与切换

文章插图
在每个 CPU 中都有一个自身的运行队列 rq,每个活动进程只出现在一个运行队列中,在多个 CPU 上同时运行一个进程是不可能的 。
运行队列是使用如下结构实现的:
struct rq {//运行队列中进程的数目unsigned long nr_running;//进程切换总数u64 nr_switches;//用于完全公平调度器的就绪队列struct cfs_rq cfs;//用于实时调度器的就绪队列struct rt_rq rt;//记录本cpu尚处于TASK_UNINTERRUPTIBLE状态的进程数,和负载信息有关unsigned long nr_uninterruptible;//curr指向当前运行的进程实例,idle 指向空闲进程的实例struct task_struct *curr, *idle;//上一次调度时的mm结构struct mm_struct *prev_mm;...};每个运行队列中有2个调度队列:CFS 调度队列 和 RT 调度队列 。
tast 作为调度实体加入到 CPU 中的调度队列中 。


推荐阅读