调度器在操作系统中扮演着至关重要的角色,它决定了CPU资源的分配和进程的执行顺序。对于调度器而言,调度时机是关键因素之一,即何时进行调度,何时将当前占用CPU的进程替换下来。这关系到进程调度生命周期的各个环节。
本章我们将重点关注调度时机的核心部分,主要分为两部分:直接调度和时间的耗尽而放弃调度。这其中涉及到源码的学习,包括schedule()函数的调用时机,主调度器和周期性调度器的工作原理,以及内核对于调度的各种场景的处理方式。
进程调度的两种方式
进程调度可以分为自愿调度和抢占调度两种方式。
- 自愿调度:是指进程因等待某种资源而改变为非RUNNING状态,如TASK_INTERRUPTIE等,此时会调用schedule()主动让出CPU资源。
- 抢占调度:当任务状态仍为RUNNING状态,但因时间片用完或更高优先级的任务出现等原因需要让出CPU时,会触发抢占调度。
schedule()函数的重要性
schedule()函数是linux调度器中最重要的函数之一,它没有参数和返回值,但却实现了内核中非常重要的功能。当需要执行调度时,直接调用schedule(),当前进程就停止了,而另外一个新进程占据了CPU。这个函数在内核中广泛被调用,是内核实现多任务处理的核心机制之一。
主调度器与周期性调度器
主调度器是实际执行调度工作的部分,它根据一定的算法和规则从就绪队列中选择合适的进程进行执行。而周期性调度器则是一种更隐蔽的调度方式,它通过定时器的中断处理程序scheduler_tick()等机制,周期性地检查当前任务的执行情况,并在必要时触发主调度器进行调度。
重新调度标志的设置与检查
在内核中,当某个进程需要被其他进程抢占或者自身需要主动让出CPU时,会设置TIF_NEED_RESCHED标志。这个标志的设置和检查是调度器工作的重要环节。当内核发现需要重新调度时,会调用主调度器进行实际的调度工作。
不同调度器的实现与特点
Linux中实现了多种调度器,如CFS完全公平调度器、实时调度器和EDF(最早截止时间优先)调度器等。每种调度器都有其特定的实现方式和适用场景。例如,CFS通过task_tick_fair()等函数实现周期性调度工作,而实时调度器则更加注重实时性和响应速度。
Linux系统的两种激活进程调度的方式
Linux系统通过主调度器和周期性调度器两种方式来激活进程调度。主调度器通过直接调用schedule()等方式来检查死锁、关闭内核抢占等然后选择合适的进程进行切换。而周期性调度器则通过定时器的中断处理程序等机制周期性地检查当前任务的执行情况并触发主调度器进行实际调度。
进程调度的时机和方式是操作系统中非常重要的部分,它涉及到多个组件和算法的协同工作。通过深入学习和理解这些组件和算法的工作原理我们可以更好地掌握操作系统的核心机制。