文章目录
- 前言
- 1.runqueue调度队列
- 2.优先级
- 3.活动队列
- 4.过期队列
- 5.active指针与expired指针
- 总结
前言
进程中的双链表结构:
cppstruct link { struct link* next; struct link* prev; } struct task_struct { //很多进程属性 struct link node; }
- 通过该结构,再在前面加入头节点,每个结点的内部就会有两个指针指向前一个和后一个结点,增加了链式管理拓展性,代码只需要维护一份
- 对于linux内核来说,会将所有的进程task_struct统一放在一张双链表里,进程也有运行队列和阻塞队列,让它运行就挂到运行队列里,让它等待阻塞就挂到相应硬件的struct里面
- 甚至可以不同的结构体对象都用链表链接、甚至二叉树哈希表等数据结构也能链接
1.runqueue调度队列
- 每一个CPU都有一个调度队列:strcut runqueue{}; 时间复杂度O(1)
- 当进程被唤醒或创建时,它会被添加到runqueue中。调度器周期性地从runqueue中选取进程,基于特定算法(如时间片轮转或公平调度)分配CPU时间。
2.优先级
普通优先级:100~139 (60~99一共40个优先级,对应+40就是分时优先级,所以数组下标-40本质就是优先级数字)
分时优先级:0~99
调度器在从runqueue中选择进程时,会优先考虑高优先级的进程 。一旦确定哪一个队列就FIFO
3.活动队列

活动队列(active queue)是runqueue的一部分,包含当前正在运行或即将运行的进程。这些进程的时间片(即分配给它们的CPU时间)尚未耗尽。活动队列是调度器的主要工作队列。
cppstruct prio_arry_t { nr_active; bitmap[5]; queue[140]; }
nr_active
表示当前处于活动状态的任务数量。这是一个计数器,记录队列中待处理的任务总数。
bitmap[5]
优先级位图(通常用位运算优化)。
作用:快速定位最高优先级的非空任务队列。
结构:数组大小为 5,每个元素是 32 位整数(共 160 位),可覆盖 140 个优先级(需按实际调整)
queue[140]
存储具体任务的队列数组,索引对应优先级。
索引范围:0 到 139 (共 140 级)。
内容 :每个
queue[i]是链表或数组
4.过期队列
过期队列(expired queue)是runqueue的另一个部分,包含那些时间片已经用完的进程。当一个进程的时间片耗尽时,它会被从活动队列移动到过期队列,等待下一次调度机会。
过期队列是活动队列的"备份"。当活动队列为空时,调度器会交换两个队列的角色(通过指针交换),使过期队列成为新的活动队列。
5.active指针与expired指针
**active指针和expired指针是两个关键指针,用于高效管理活动队列和过期队列。**它们指向相应的队列数据结构,简化队列切换过程。
- active指针:指向当前的活动队列。调度器总是从active指针指向的队列中选择进程运行。
- expired指针:指向当前的过期队列。当进程时间片用完时,它被添加到expired指针指向的队列。
总结
这些概念共同构成了高效公平的进程调度系统。runqueue作为基础队列,优先级指导调度顺序,活动队列和过期队列分离运行与等待进程,active指针和expired指针通过快速交换实现队列切换。这种设计确保了CPU资源公平分配(如避免进程饥饿),同时保持高性能。
