linux2.4到linux2.6内核调度(2)

1) prio_array_t *active, *expired, arrays[2]

runqueue 中最关键的数据结构。每个 CPU 的就绪队列按时间片是否用完分为两部分,分别通过 active 指针和 expired 指针访问,active 指向时间片没用完、当前可被调度的就绪进程,expired 指向时间片已用完的就绪进程。每一类就绪进程都用一个 struct prio_array 的结构表示:

struct prio_array {

                                          int nr_active;                                          /* 本进程组中的进程数 */

                                          struct list_head queue[MAX_PRIO];

                                                                                                                                               /* 以优先级为索引的 HASH 表,见下 */

                                          unsigned long bitmap[BITMAP_SIZE];

                                                                                                                                               /* 加速以上 HASH 表访问的位图,见下 */

};

图1:active、expired 数组示例



图中的 task 并不是 task_struct 结构指针,而是 task_struct::run_list,这是一个小技巧,详见下文 run_list 的解释。

在 2.4 版的内核里,查找最佳候选就绪进程的过程是在调度器 schedule() 中进行的,每一次调度都要进行一次(在 for 循环中调用 goodness()),这种查找过程与当前就绪进程的个数相关,因此,查找所耗费的时间是 O(n) 级的,n 是当前就绪进程个数。正因为如此,调度动作的执行时间就和当前系统负载相关,无法给定一个上限,这与实时性的要求相违背。

在新的 O(1) 调度中,这一查找过程分解为 n 步,每一步所耗费的时间都是 O(1) 量级的。

prio_array 中包含一个就绪队列数组,数组的索引是进程的优先级(共 140 级,详见下 "static_prio" 属性的说明),相同优先级的进程放置在相应数组元素的链表 queue 中。调度时直接给出就绪队列 active 中具有最高优先级的链表中的第一项作为候选进程(参见"调度器"),而优先级的计算过程则分布到各个进程的执行过程中进行(见"优化了的优先级计算方法")。

为了加速寻找存在就绪进程的链表,2.6 核心又建立了一个位映射数组来对应每一个优先级链表,如果该优先级链表非空,则对应位为 1,否则为 0。核心还要求每个体系结构都构造一个 sched_find_first_bit() 函数来执行这一搜索操作,快速定位第一个非空的就绪进程链表。

采用这种将集中计算过程分散进行的算法,保证了调度器运行的时间上限,同时在内存中保留更加丰富的信息的做法也加速了候选进程的定位过程。这一变化简单而又高效,是 2.6 内核中的亮点之一。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值