共有回帖数 0 个
-
SD调度器的源码1,可以从kernel.org自己在2.6.22之前找
2,可以在这里在线看
http://lxr.linux.no/#linux+v2.6.22.19/kernel/sched.c
linux调度器从2.4到2.6是个巨大的变革。
2.4内核的调度器我就不详细解说了,其实就是从链表中找最高优先级运行,然
后重新计算,这样的话,负载轻的完全没啥问题,但负载重的话因为是O(n)的查
找,后果会很严重。
2.6的内核从一开始是由现在的主线调度器CFS的作者Ingo Molnar着手重新设计。
最大的特色是这是一个由两个大小是MAX_PRIO(默认是140)的优先级数组组成。
每次调度的时候会从active数组抽取最高优先级的队列头的第一个进程来调度,
调度结束后进程的优先级会用进程的睡眠时间和运行来重新计算,然后放到expired
数组,也就是动态优先级。这样pick_next的时间复杂度就变成了1,并且改善了“一点”
的交互性。但害处也是有的,这样的优先级判断其实是不准确的,在程序下稍作手脚就会
影响系统的交互式进程的响应了。
SD调度器全名是Staircase-Deadline,这个调度器由Con Kolivas开发,
SD调度器的进程的优先级是静态的,最基础的优先级来源于task_struct结构体的
static_prio,也就是用户的nice值,sd调度器的运行队列结构体如下:
struct rq {
spinlock_t lock;
unsigned long nr_running;
unsigned long raw_weighted_load;
unsigned long long nr_switches;
unsigned long nr_uninterruptible;
unsigned long expired_timestamp;
unsigned long long most_recent_timestamp;
struct task_struct *curr, *idle;
unsigned long next_balance;
struct mm_struct *prev_mm;
struct prio_array *active, *expired, arrays[2];
int best_expired_prio;
atomic_t nr_iowait;
struct lock_class_key rq_lock_key;
};
大家把SMP和SCHEDSTATS先忽略了。首先调度器结构体成员lock就是runqueue的自旋锁,
是用来确保多CPU的安全。nr_running是指在该CPU的runqueue上的TASK_RUNNING进程的个数。
nr_switches是上下文切换的次数。nr_uninterruptible是TASK_UNINTERRUPTABLE睡眠进程的个数
curr是当前运行着的进程,active, expired, arrays就是运行队列了,不过可以把expired
给忽略了,因为SD调度器是多级反馈队列。
struct prio_array {
unsigned int nr_active;
DECLARE_BITMAP(bitmap, MAX_PRIO+1); /* include 1 bit for delimiter */
struct list_head queue[MAX_PRIO];
};
nr_active是多级反馈队列里的进程个数。
bitmap是代表对应优先级的队列头有没有进程。
然后queue你懂的,是队列头
SD调度器的策略就是这样:首先每个进程的初始优先级都是static_prio,也就是进程原本
应该在queue队列头数组的static_prio位置。当一个进程运行掉所有时间片,那么进程的
优先级就会降1。
假如一个进程运行完时间片,然后他的优先级是0,那么就会掉到1.
+-------------+
| -1 |
+-------------+
| 0 |-----+
+-------------+ |
| 1 | ---+
+-------------+
| 2 |
+-------------+

那么进程的优先级如果彻底降到最后然后又没办法反弹了,那么不是
等于被憋死在最低优先级了么?当然不是,SD调度器在碰到这种情况的时候,
进程的优先级会回到static_prio
好处就体验在这了。低优先级的进程比如那些计算什么什么算式啊,
那些的优先级就会不断的下降,然后又回到原来的优先级。而高优先级的
进程呢?就会保留着剩下的时间片,然后站在台阶上,很慢很慢的下降
其实这样呢,还有一个秘密,那就是如果进程在运行少于1毫秒后睡眠
或者yield,那么优先级就会一直保持。抢占的过程很简单,就
是进程优先级大于或等于当前运行进程的优先级这样的话,那么就抢占成功
被抢占的进程的时间片和优先级会保留,高优先级的进程就能获得很好的
响应,然后低优先级的进程因为有这种优先级下降然后反弹的策略,
所以不会因为长期有高优先级进程在队列而饿死,但又不会很容易霸占到
高优先级进程的执行权,互相的在平衡者,然后结果自然就是公平调度了。
写这个调度器分析的原因呢,是因为这个调度器实在是很适合在桌面的使用,而且十分的高效,也把多级反馈队列用到了极致。我的RIFS调度器里面的优先级下降跟SD调度器一样也是用了类似的反弹机制,不过我的反弹是直接回到原来的优先级的。而且如果进程运行时间少于time_slice() / 2的话,我的调度器会增加优先级的。不得不说,SD调度器真的很经典,很好而且响应力也真的很不错。
也希望Linux的调度器重视普通桌面用户的体验,官方也可以在源码内用make menuconfig,make xconfig的方法来让用户选择是普通桌面电脑还是服务器,不要一味的偏袒。我如果不是情非得已我是不会有写RIFS调度器这个考虑的
楼主 2015-11-05 13:38 回复
Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号
意见反馈 |
关于直线 |
版权声明 |
会员须知