进程调度之实时调度策略(SCHED_FIFO、SCHED_RR、MAX_RT_PRIO实时优先级)

1. 前言

Linux提供了两种实时调度策略:SCHED_FIFO和SCHED_RR
普通的、非实时的调度策略是SCHED__NORMAL
借助调度类的框架,这些实时策略并不被完全公平调度器来管理, 而是被一个特殊的实时调度器管理。具体的实现定义在文件kernel/sched_rt.c中,在接下来的内容中我们将讨论实时调度策略和算法

2. 各种调度策略

SCHED_FIFO
SCHED_FIFO实现了一种简单的、先入先出的调度算法:它不使用时间片
特点:

  • 处于可运行状态的SCHED_FIFO级的进程会比任何SCHED_NORMAL级的进程都先得到调用
    一旦一个SCHED_FIFO级进程处于可执行状态,就会一直执行,直到它自己受阻塞或显式地释放处理器为止,它不基于时间片,可以一直执行下去
  • 只有更高优先级的SCHED_FIFO或者SCHED_RR任务才能抢占SCHED_FIFO任务
    如果有两个或者更多的同优先级的SCHED_FIFO级进程,它们会轮流执行,但是依然只有在它们愿意让出处理器时才会退出
  • 只要有SCHED_FIFO级进程在执行,其他级别较低的进程就只能等待它变为不可运行态后才有机会执行

2.1 SCHED_RR

SCHED_RR与SCHED_FIFO大体相同,只是SCHED_RR级的进程在耗尽事先分配给它的时间后就不能再继续执行了
也就是说,SCHED_RR是带有时间片的SCHED_FIFO——这是一 种实时轮流调度算法。
特点:

  • 当SCHED_RR任务耗尽它的时间片时,在同一优先级的其他实时进程被轮流调度 时间片只用来重新调度同一优先级的进程
  • 对于SCHED_FIFO进程, 优先级总是立即抢占低优先级,但低优先级进程决不能抢占SCHED_RR任务,即使它的时间片耗尽

2.2 软实时

上面介绍的这两种实时算法实现的都是静态优先级。内核不为实时进程计算动态优先级。这能保证给定优先级別的实时进程总能抢占优先级比它低的进程。
Linux的实时调度算法提供了一种软实时工作方式
软实时的含义是:内核调度进程,尽力使进程在它的限定时间到来前运行,但内核不保证总能满足这些进程的要求。相反,硬实时系统证在一定条件下,可以满足任何调度的要求。Linux对于实时任务的调度不做任何保证。虽然不能保证硬实时工作方式,但Linux的实时调度算法的性能还是很不错的。2.6版的内核可以满足严格的时间要求。

2.3 实时优先级(MAX_RT_PRIO)

实时优先级范围从0到MAX_RT_PRIO减1
默认情况下,MAC_RT_RTIO为100——所以默认的实时优先级范围从0到99
SCHED_NORMAL级进程的noce值共享了这个取值空间。它的取值范围从MAC_RT_PRIO到(MAC_RT_PRIO+40)。也就是说,在默认情况下,nice值从-20到+19直接对应的是从100到139的实时优先级范围。

3. 参考文章

进程调度队列是如何组织的: 在 Linux 内核中,进程调度队列是由多个就绪队列(runqueue)组成的。每个 CPU 都有一个就绪队列,用于保存可以被调度进程。就绪队列是一个双向链表,每个链表节点对应一个进程。就绪队列使用了一些优化技巧,例如旋转数组(rotating bitmap)和红黑树(red-black tree),以提高调度效率。 三种调度类型(SCHED_FIFO, SCHED_RR, SCHED_OTHER)的实现过程: Linux 内核中支持三种调度类型: - SCHED_FIFO:先进先出调度策略进程一旦被调度,将一直占用 CPU 直到自愿放弃或者被其他进程抢占。 - SCHED_RR:时间片轮转调度策略进程被分配固定的时间片,当时间片用完或者进程主动放弃 CPU 时,进程就会被放回到就绪队列中,等待下一次调度。 - SCHED_OTHER:CFS(Completely Fair Scheduler)调度策略,基于进程的虚拟运行时间(vruntime)来决定进程优先级优先级较高的进程调度的机会更高。 在 Linux 内核中,这三种调度类型的实现都是基于调度类(sched_class)的概念。每个调度类都包含了一组函数指针,用于实现进程调度相关的操作。不同的调度类实现不同的调度策略优先级是如何定义和动态变化的: 在 Linux 内核中,进程优先级是一个动态变化的值,取值范围为 -20 到 19。优先级较高的进程会更容易被调度进程优先级调度类的实现决定,不同的调度类可以有不同的优先级计算方式。 时间片的赋值?它与优先级的关系? 在 Linux 内核中,时间片的赋值与优先级有关。时间片的大小由进程优先级决定,优先级越高的进程分配的时间片越长。具体来说,时间片的大小可以通过以下公式计算: time_slice = 100 * 2 ^ (MAX_PRIO - prio) 其中,MAX_PRIO进程优先级的最大值,prio进程优先级。时间片的单位是 jiffies(时钟滴答数),具体的大小可以通过 kernel/sched/core.c 中的 time_slice() 函数计算。 重点分析内核数据结构 task_struct(在 include/linux/sched.h 中)和调度函数 schedule()(在 kernel/sched.c 中): task_struct 结构体是 Linux 内核中描述进程的主要数据结构,其中包含了进程的各种信息,包括进程 ID、优先级、状态等等。task_struct 结构体比较庞大,其中包含了多个子结构体,例如 thread_info、mm_struct、fs_struct 等等。 schedule() 函数是 Linux 内核中实现进程调度的核心函数,它由内核定时器触发,用于从就绪队列中选择下一个需要运行的进程schedule() 函数首先会检查当前 CPU 上是否有正在运行的进程,如果有,则不进行调度;否则,它会从就绪队列中选择下一个进程,并将其调度到 CPU 上运行。如果就绪队列为空,则 schedule() 函数会将当前 CPU 切换到 idle 进程上,以节省 CPU 资源。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值