复习
本次课回答的问题
本次课主要内容
中断机制
处理器调度问题的简化假设
假设当前 $T_i$ 运行
我们的 thread-os.c 实际上实现了 Round-Robin 的调度器
UNIX niceness
taskset -c 0 nice -n 19 yes > /dev/null &
taskset -c 0 nice -n 9 yes > /dev/null &
系统里有两个进程
Round-Robin
不会设置优先级?让系统自动设定!
试图去模拟一个 “Ideal Multi-Tasking CPU”:
“让系统里的所有进程尽可能公平地共享处理器”
操作系统具有对物理时钟的 “绝对控制”
const int sched_prio_to_weight[40] = {
/* -20 */ 88761, 71755, 56483, 46273, 36291,
/* -15 */ 29154, 23254, 18705, 14949, 11916,
/* -10 */ 9548, 7620, 6100, 4904, 3906,
/* -5 */ 3121, 2501, 1991, 1586, 1277,
/* 0 */ 1024, 820, 655, 526, 423,
/* 5 */ 335, 272, 215, 172, 137,
/* 10 */ 110, 87, 70, 56, 45,
/* 15 */ 36, 29, 23, 18, 15,
};
子进程继承父进程的 vruntime
static void task_fork_fair(struct task_struct *p) {
struct sched_entity *se = &p->se, *curr;
...
rq_lock(rq, &rf);
update_rq_clock(rq);
cfs_rq = task_cfs_rq(current);
curr = cfs_rq->curr;
if (curr) {
update_curr(cfs_rq);
se->vruntime = curr->vruntime; // 继承父进程的 vruntime
}
place_entity(cfs_rq, se, 1);
...
I/O (例如 1 分钟) 以后回来 vruntime 严重落后
Linux 的实现
if (renorm && curr)
se->vruntime += cfs_rq->min_vruntime;
vruntime 有优先级的 “倍数”
a < b
不再代表 “小于”!假设:系统中最近、最远的时刻差不超过数轴的一半
bool less(u64 a, u64 b) {
return (i64)(a - b) < 0;
}
用什么数据结构维护所有进程的 vruntime?
道理还挺简单的
考虑三种情况:Producer, Consumer, while (1)
while (1)
完全饥饿 → 需要定期把所有人优先级 “拉平”void xiao_zhang() { // 高优先级
sleep(1); // 休息一下先
mutex_lock(&wc);
...
}
void xi_zhu_ren() { // 中优先级
while (1) ;
}
void jyy() { // 最低优先级
mutex_lock(&wc);
...
}
jyy 在持有互斥锁的时候被赶下了处理器……
Sojourner “探路者” (PathFinder)
bc_dist
task: 分发任务 (中)bc_sched
task: 总线调度 (高)select -> pipeIoctl -> selNodeAdd -> mutex_lock
pipeWrite -> mutex_lock
Linux: CFS 凑合用吧
还没完:我们的计算机系统可是多核心、多线程的!
“And you have to realize that there are not very many things that have aged as well as the scheduler. Which is just another proof that scheduling is easy.” ——Linus Torvalds, 2001
Linus 以为调度是个挺简单的问题?
既不能简单地 “分配线程到处理器”
也不能简单地 “谁空丢给谁”
多处理器调度的两难境地
还是刚才服务器的例子
更糟糕的是,优先级解决不了这个问题……
namespaces (7), cgroups (7)
Snapdragon 888
“Dark silicon” 时代的困境
软件可以配置 CPU 的工作模式
共享内存只是假象
基本的假设可能不再成立
$ time taskset -c 0 ./a.out
$ time taskset -c 0,1 ./a.out
分配了 1/2 的处理器资源,反而速度更快了
😂😂😂 我讲不下去了
复杂的系统无人可以掌控
调度是复杂、有着深远考虑的困难问题
巨大的设计空间
操作系统不 (完全) 背这个锅
本次课回答的问题
Take-away messages