趣谈 Linux 操作系统
刘超
前网易杭州研究院云计算技术部首席架构师
85458 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 72 讲
趣谈 Linux 操作系统
15
15
1.0x
00:00/00:00
登录|注册

16 | 调度(中):主动调度是如何发生的?

课堂练习
总结时刻
指令指针的保存与恢复
进程上下文切换
主动调度
调度发生方式
进程调度

该思维导图由 AI 生成,仅供参考

上一节,我们为调度准备了这么多的数据结构,这一节我们来看调度是如何发生的。
所谓进程调度,其实就是一个人在做 A 项目,在某个时刻,换成做 B 项目去了。发生这种情况,主要有两种方式。
方式一:A 项目做着做着,发现里面有一条指令 sleep,也就是要休息一下,或者在等待某个 I/O 事件。那没办法了,就要主动让出 CPU,然后可以开始做 B 项目。
方式二:A 项目做着做着,旷日持久,实在受不了了。项目经理介入了,说这个项目 A 先停停,B 项目也要做一下,要不然 B 项目该投诉了。

主动调度

我们这一节先来看方式一,主动调度。
这里我找了几个代码片段。第一个片段是 Btrfs,等待一个写入Btrfs(B-Tree)是一种文件系统,感兴趣你可以自己去了解一下。
这个片段可以看作写入块设备的一个典型场景。写入需要一段时间,这段时间用不上 CPU,还不如主动让给其他进程。
static void btrfs_wait_for_no_snapshoting_writes(struct btrfs_root *root)
{
......
do {
prepare_to_wait(&root->subv_writers->wait, &wait,
TASK_UNINTERRUPTIBLE);
writers = percpu_counter_sum(&root->subv_writers->counter);
if (writers)
schedule();
finish_wait(&root->subv_writers->wait, &wait);
} while (writers);
}
另外一个例子是,从 Tap 网络设备等待一个读取。Tap 网络设备是虚拟机使用的网络设备。当没有数据到来的时候,它也需要等待,所以也会选择把 CPU 让给其他进程。
static ssize_t tap_do_read(struct tap_queue *q,
struct iov_iter *to,
int noblock, struct sk_buff *skb)
{
......
while (1) {
if (!noblock)
prepare_to_wait(sk_sleep(&q->sk), &wait,
TASK_INTERRUPTIBLE);
......
/* Nothing to read, let's sleep */
schedule();
}
......
}
你应该知道,计算机主要处理计算、网络、存储三个方面。计算主要是 CPU 和内存的合作;网络和存储则多是和外部设备的合作;在操作外部设备的时候,往往需要让出 CPU,就像上面两段代码一样,选择调用 schedule() 函数。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了进程调度的发生方式,主要分为主动调度和被动调度。主动调度发生在进程自身需要让出CPU的情况下,通过调用schedule()函数来主动让出CPU,让其他进程执行。文章通过代码片段展示了两种主动调度的情况,分别是Btrfs文件系统等待写入和Tap网络设备等待读取。接着详细解释了schedule()函数的调用过程,包括获取下一个任务、上下文切换等步骤。文章通过代码解析展示了调度类的调用过程,以及CFS调度类的pick_next_task_fair函数的实现。此外,文章还介绍了进程上下文切换的实现细节,包括内存空间的切换、寄存器和栈的切换,以及Per CPU的结构体tss的作用。通过深入的代码分析,生动地展现了主动调度的发生过程,对于理解进程调度机制有很好的帮助。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《趣谈 Linux 操作系统》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(54)

  • 最新
  • 精选
  • 憨人
    进程切换需要搞明白:我从哪里来,我要到哪里去

    作者回复: 这句话赞

    2019-05-17
    27
  • 安排
    proc文件系统里面可以看运行时间和切换次数,还可以看自愿切换和非自愿切换次数。 老师请教一个问题,A切到B, B切到C,C切到A,当最后切换回A的时候,A要知道自己是从C切换过来的,也就是last,这样做的目的是什么呢?A要对C做什么善后操作吗?

    作者回复: 是的 finish_task_switch完成清理工作

    2019-05-03
    27
  • 刘強
    看了三遍,因为有一些基础,大概明白了。我觉得有个地方很巧妙。当函数返回的时候,由于切换了上下文,包括栈指针,所以一个进程函数执行return返回到了另一个进程,也就是完成了进程的切换。由此也可以看出,cpu也是比较"笨的",它只提供了基本的机制,至于如何利用这种机制,玩出花样,那就是各个操作系统自由发挥了。

    作者回复: 是的,这一点比较绕

    2019-05-05
    4
    16
  • 尚墨
    刘老师,每个用户的进程都会被分配一个内核栈吗?

    作者回复: 是的

    2019-05-08
    2
    9
  • kdb_reboot
    补充一下,看了最后的那张图,感觉切换,就是切内核态的 stack/rsp/pc, 这样下一个任务就能找到在哪执行了,以及继续怎么执行, 而内核态共享一片内存空间,所以不需要mm_switch,切换完了,返回用户态,用户态的stack/rsp/pc都被切换了, 而用户态的内存空间需要单独切换 老师,我理解的对吧?

    作者回复: 是的

    2019-07-27
    8
  • 蹦哒
    “cpu_init会给每一个 CPU 关联一个 TSS,然后将 TR 指向这个 TSS,然后在操作系统的运行过程中,TR 就不切换了,永远指向这个 TSS” 看到这里,想到了一个设计模式:享元模式(Flyweight Design Pattern)

    作者回复: 牛,这是从设计模式专栏过来的吧

    2020-06-14
    7
  • kdb_reboot
    看起来ps 里面的TIME就是进程的 cpu runtime吧; 查看上下文切换,可以用cat /proc/x/status

    作者回复: 赞

    2019-07-27
    6
  • kdb_reboot
    关于指令指针的讲解,厉害了... 专栏有时候可以反者看, 先看最后总结,然后往上顺藤模块看你的分析 同时在读的书:lkd/ulk, 推荐给大家

    作者回复: 先看总结也挺好的

    2019-07-27
    3
  • garlic
    通过ps -o etime= -p "$$" 可以 查看,进程的运行时间, 通过/proc/{pid}/status 中的 voluntary_ctxt_switches: nonvoluntary_ctxt_switches: 可以看到主动调度和抢占调度的次数, 也可以单独安装sysstat 使用pidstat -w 查看相关进程的调度信息 https://garlicspace.com/2019/07/20/查看进程运行时间及上下文切换次数/

    作者回复: 赞

    2019-07-20
    2
  • 栋能
    我有两个问题,希望老师解解惑: 1.文中说进程切换会从红黑树中找到最左结点,如果不等于当前进程,则切换。但如果更新vruntime之后,树结构还是没变呢,即最左还是等于当前进程,那我当前进程切换不是又没效果了吗?(这点有疑问,是我理解vruntime是公平的,但主动调度一定存在某种情况,如vruntime变化不大,树结构不变的?) 2.在指令指针的恢复与保存这部分内容中,你说A调用__schedule进行切换,在运行到finish_task_switch时进程已经是B了。你觉得这里没有问题,是因为A、B进程都是调用过__schedule方法进行进程切换,最后都执行finish_task_switch就是圆满了。可是进程切换除了主动调用之外,还有时间片用完,如B进程可能并没有调用过__schedule,那如果A进程切换,导致B进程执行finish_task_switch方法,那这是不是个问题呢?本来进程B并不需要执行它的。

    作者回复: 1.如果最左面的节点还是自己,并且自己还能运行,也即还是running状态,那就接着运行,说明时间片用完了,但是没有更加高级的需要运行,如果是等待IO,那就不是running状态,则不在树中。 2.调度第一定律,B如果当年被调度走,哪怕是时间片到,也是调用了schedule的

    2019-07-16
    5
    2
收起评论
显示
设置
留言
54
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部