linux调度器之主调度器框架

本文详细介绍了Linux内核中的进程状态,包括阻塞态、就绪态和运行态,强调了调度器在进程管理中的角色。接着探讨了Linux调度器的相关文件,并重点关注了主调度器schedule()函数,分析了其在自主调度、用户态抢占和内核态抢占中的应用。通过对schedule()函数的剖析,展示了如何在不同场景下确保进程的正确调度和上下文切换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

进程是操作系统提供的最古老,最重要的抽象之一,它对开发人员和操作人员隐藏了两个基本的硬件资源:处理器和存储器。进程的重要性在于它营造出个数不受物理处理器限制的虚拟处理器并为每个虚拟处理器配备了独立的,容量不受物理内存大小限制的内存空间。这些虚拟处理器为应用程序模拟出一个和物理处理器几乎相同的环境:每个虚拟处理器都拥有独立的,与物理处理器一样的寄存器集合;每个虚拟处理器可以使用同样的地址访问到的却是各自的存储单元;更重要的是,这么多虚拟处理器可以同时并发运行各自的程序,哪怕实际上只存在一个物理处理器。这就是本章讨论的重点:进程调度。

1.1         进程状态

虽然在很多操作系统里进程的状态多达五六,甚至八九种,但是从调度器的角度,进程的状态只有三种:阻塞态,就绪态和运行态。

处于阻塞态的进程不参与进程调度,事实上调度器在分配处理器时间时根本不知道阻塞态进程的存在。阻塞态进程要想参与调度,必须有一个‘第三方’将其提交给调度器,不然这个进程就是一个虽然存在但再也无法运行的‘植物人’。比如一个进程调用sleep()函数休眠一段时间,该进程就从当前运行进入阻塞态,从此不再受调度器的调遣,不再有机会占据处理器。等到指定的休眠时间到达,操作系统的定时器模块作为‘第三方’,将该进程提交给调度器,使其再度参与调度,又有机会成为当前运行进程。

与阻塞态不受调度器控制不同,就绪态和运行态进程都处于调度器的管辖之下。处于就绪态的进程本该运行于处理器上,可是调度器为了平衡众多进程对处理器时间的需求,让该进程暂时停下来听候调遣而安排其它进程在处理器上运行。就绪进程和阻塞进程共同点是都没有占用处理器,区别是阻塞态进程即使在处理器空闲时也不能运行,而就绪进程处于‘预备役’状态,只要处理器空闲或‘时机成熟’马上能运行于处理器上。就绪进程在调度器的队列里排队等候调遣,不同调度算法有各自的排队方式,如linux的完全公平(CFS)算法使用基于虚拟运行时间的红黑树,实时(RT)算法为每个调度优先级设置一条先入先出的队列。

运行态进程又叫当前进程,就是当前正在处理器上运行的进程。由于它占用了宝贵的处理器时间,在很多调度算法里当前进程都是重点监控对象,它的运行时间受到严密监视。一旦发现运行时间超标就会将其从‘现役’转为‘预备役’,进入就绪态,把处理器让给其它就绪进程(当然必须有其它就绪进程存在)。linux对当前进程运行时间的监控是在操作系统的tick中断里完成的,间隔从10毫秒到1毫秒不等。即使是这样的周期CFS算法的设计者还觉得不够精确,又设置了精度为纳秒级的高精度定时器(hrtimer)来监控当前进程,保证其占用的处理器时间严格符合预先给予的配额。

进程的三种基本状态在linux里并不直观。阻塞态有很多表达方式用以表示更精细的状态,比如常用的TASK_INTERRUPTIBLETASK_UNINTERRUPTIBLE。当前进程的状态表示为TASK_RUNNING,可是就绪进程的状态也是用TASK_RUNNING表示。这不会造成混淆,因为当前运行进程是有专门变量记录的,而就绪进程则统一排列在运行队列中。在linuxTASK_RUNNING的值是0,其它状态值都非0。为运行态和就绪态设置相同值的一个好处是调度器可以很简单地判断一个进程是否能还能继续参与调度:只要状态非0的进程就是应该进入阻塞态的进程,调度器发现这样的进程就将其从调度器脱离开,不再竞争处理器。

1.2         Linux调度器相关文件

调度器是Linux内核中变化较多的模块,功能和性能随着应用的拓展不断增强,代码结构也随着需求的变化持续重构和优化。下表列出了本章将要涉及的,与调度器相关的源代码所在的文件。由于变化较大,可能随着内核版本的持续升级很快表中内容就与最新版本不符合了。

文件名

作用

linux_2.6.34-rc6/kernel/sched.c

该文件是调度器主体,包含调度器初始化,主调度器框架,调度器相关的API,各个具体调度算法也就是调度类的公共函数,用以支持分组调度的处理器子系统。

linux_2.6.34-rc6/kernel/sched_fair.c

该文件实现完全公平调度(CFS)算法和多处理器的负载平衡,与CFS调度类对应

linux_2.6.34-rc6/kernel/sched_rt.c

该文件实现实时调度(RT)算法,与RT调度类对应

### Linux CFS 调度器工作原理与实现 #### 1. 完全公平调度器(CFS)概述 完全公平调度器(Completely Fair Scheduler, CFS)是现代 Linux 内核中的要调算法之一。它旨在通过动态调整进程的执行时间来提供更公平的任务分配机制[^1]。 CFS 的核心目标是最小化平均调延迟并最大化系统的吞吐量。为了达到这一目的,CFS 使用了一种基于虚拟运行时间(vruntime)的概念来进行任务调度[^2]。 --- #### 2. 关键数据结构 以下是 CFS 中涉及的要数据结构: - **`struct rq`**: 表示 CPU 就绪队列的整体状态。 ```c struct rq { struct cfs_rq cfs; struct rt_rq rt; struct dl_rq dl; }; ``` - **`struct rb_root_cached`**: 红黑树用于维护就绪队列中任务的时间顺序关系。 ```c struct rb_root_cached { struct rb_root rb_root; // 红黑树的根节点 struct rb_node *rb_leftmost; // 红黑树中最左侧节点 }; ``` - **`struct cfs_rq`**: 描述 CFS 类型的就绪队列。 ```c struct cfs_rq { struct load_weight load; // 所有调实体的总权重 unsigned int nr_running; // 当前正在运行的调实体数量 u64 min_vruntime; // 队列上最小的虚拟运行时间 struct rb_root_cached tasks_timeline; // 时间线红黑树 }; ``` 这些数据结构共同构成了 CFS 的基础框架,支持高效的任务管理和调决策。 --- #### 3. 虚拟运行时间(vRuntime) CFS 引入了一个名为虚拟运行时间(vRuntime)的概念,用来衡量每个任务已经消耗了多少相对资源。具体计算方式如下: \[ vruntime_i = \frac{real\_time}{weight} \] 其中 \( real\_time \) 是实际运行时间,\( weight \) 则表示该任务的优先级权重。较低的 `vruntime` 值意味着更高的优先权被赋予给尚未获得足够 CPU 时间片的任务。 当需要选择下一个要执行的任务时,CFS 总是从具有最低 `min_vruntime` 的任务开始,并将其放置到当前活动的核心上去运行。 --- #### 4. 进程选择逻辑 在每次切换上下文之前,内核会调用函数 `pick_next_task()` 来决定哪个任务应该被执行。此过程遵循以下原则: - 如果存在任何实时任务,则立即挑选最高优先级的一个; - 否则,在普通用户空间进程中寻找拥有最少累积 vruntimes 的那个实例作为候选者。 这种策略确保即使长时间等待的小型作业也能及时得到服务机会而不会饿死其他大型负载程序的需求平衡之间找到最佳折衷方案。 --- #### 5. 新增任务加入流程 每当创建一个新的可运行态线程或者现有线程变为可以继续前进的状态之后都会触发一次插入动作。此时系统将按照既定规则把它们挂载至对应类型的 RB Tree 上面去形成有序排列以便后续快速检索定位最近可用项完成即时响应需求。 代码片段展示如何向红黑树添加新条目: ```c static void enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) { /* 更新相关统计信息 */ insert_rb_tree(&cfs_rq->tasks_timeline.rb_root, se); } ``` 上述方法利用标准库提供的工具完成了复杂的数据组织操作从而简化了高层接口设计难同时也提高了整体性能表现水平达到了预期效果. --- #### 6. 调延迟能力评估 理论上讲只要合理配置参数就可以让大多数情况下单个常规级别下的请求能够在几十微秒之内得到有效满足因此对于绝大多数应用场景而言这样的效率已然绰绰有余完全可以胜任日常所需任务处理要求。 然而需要注意的是极端条件下比如大量并发访问竞争激烈场景下可能会导致个别特殊情形超出理想范围之外所以还需要结合实际情况灵活调整优化措施以适应不同业务环境的具体特性差异之处做出相应改进提升综合服务能力质量水准达成最终目标追求极致用户体验感受价值最大化成果展现形式多样化呈现出来供大家参考借鉴学习进步成长发展共赢未来无限可能前景光明灿烂辉煌成就非凡卓越不凡人生旅途精彩纷呈不断超越自我极限挑战未知领域探索发现更多美好事物创造属于自己的传奇故事书写独一无二的历史篇章留下永恒的记忆痕迹影响深远意义重大贡献突出令人敬仰赞叹不已! --- ###
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值