03 | 基础篇:经常说的 CPU 上下文切换是什么意思?(上)

2018-11-26 倪朋飞
《Linux 性能优化实战》
课程介绍


讲述:冯永吉

时长:大小5.80M


你好,我是倪朋飞。
上一节,我给你讲了要怎么理解平均负载( Load Average),并用三个案例展示了不同场景下平均负载升高的分析方法。这其中,多个进程竞争 CPU 就是一个经常被我们忽视的问题。
我想你一定很好奇,进程在竞争 CPU 的时候并没有真正运行,为什么还会导致系统的负载升高呢?看到今天的主题,你应该已经猜到了,CPU 上下文切换就是罪魁祸首。
我们都知道,Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉。
而在每个任务运行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器(Program Counter,PC)。
CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。而程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。...

展开全文
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。

精选留言

  • D白菜
    2018-11-26
    今天的课抽象的东西很多,还需要时间理解消化。对学习做了个简单的总结,初学者有何很多地方理解不对,请老师和童鞋们多多指正。 1、多任务竞争CPU,cpu变换任务的时候进行CPU上下文切换(context switch)。CPU执行任务有4种方式:进程、线程、或者硬件通过触发信号导致中断的调用。 2、当切换任务的时候,需要记录任务当前的状态和获取下一任务的信息和地址(指针),这就是上下文的内容。因此,上下文是指某一时间点CPU寄存器(CPU register)和程序计数器(PC)的内容, 广义上还包括内存中进程的虚拟地址映射信息. 3、上下文切换的过程: (1)记录当前任务的上下文(即寄存器和计算器等所有的状态); (2)找到新任务的上下文并加载; (3)切换到新任务的程序计算器位置,恢复其任务。 4、根据任务的执行形式,相应的下上文切换,有进程上下文切换、线程上下文切换、以及中断上下文切换三类。 5、进程和线程的区别: 进程是资源分配和执行的基本单位;线程是任务调度和运行的基本单位。线程没有资源,进程给指针提供虚拟内存、栈、变量等共享资源,而线程可以共享进程的资源。 6、进程上下文切换:是指从一个进程切换到另一个进程。 (1)进程运行态为内核运行态和进程运行态。内核空间态资源包括内核的堆栈、寄存器等;用户空间态资源包括虚拟内存、栈、变量、正文、数据等 (2)系统调用(软中断)在内核态完成的,需要进行2次CPU上下文切换(用户空间-->内核空间-->用户空间),不涉及用户态资源,也不会切换进程。 (3)进程是由内核来管理和调度的,进程的切换只能发生在内核态。所以,进程的上下文不仅包括了用户空间的资源,也包括内核空间资源。 (4)进程的上下文切换过程: (a)接收到切换信号,挂起进程,记录当前进程的虚拟内存、栈等资源存储; (b)将这个进程在 CPU 中的上下文状态存储于起来; (c)然后在内存中检索下一个进程的上下文; (d)并将其加载到 CPU的寄存器中恢复; (3)还需要刷新进程的虚拟内存和用户栈; (f)最后跳转到程序计数器所指向的位置(即跳转到进程被中断时的代码行),以恢复该进程。 (5)、下列将会触发进程上下文切换的场景: (a)、根据调度策略,将CPU时间划片为对应的时间片,当时间片耗尽,当前进程必须挂起。 (b)、资源不足的,在获取到足够资源之前进程挂起。 (c)、进程sleep挂起进程。 (d)、高优先级进程导致当前进度挂起 (e)、硬件中断,导致当前进程挂起 7、线程上下文切换: (1)、不通进程之间的线程上下文切换,其过程和进程上下文切换大致相同。 (2)、进程内部的线程进上下文切换。不需要切换进程的用户资源,只需要切换线程私有的数据和寄存器等。这会比进程上下文进程切换消耗的资源少,所以多线程相比多进程的优势。 8、中断上下文切换 快速响应硬件的事件,中断处理会打断进程的正常调度和执行。同一CPU内,硬件中断优先级高于进程。切换过程类似于系统调用的时候,不涉及到用户运行态资源。但大量的中断上下文切换同样可能引发性能问题。 有些疑惑,想请教老师, (1)从用户态和内核态之间的转变过程通过系统调用,那么系统调用属于一种上下文切换吗?如果是上下文切换,属于哪一类上下文切换呢,和进程上下文切换的关系是什么? (2)指令寄存器和程序计算器,这两个东东比较模糊。
    展开

    作者回复: 👍课代表来了 (1)系统调用属于同进程内的CPU上下文切换; (2)分别是CPU用来存储指令和下一条要执行指令的寄存器

    共 8 条评论
    212
  • 小花
    2019-03-25
    进程切换我想到了很多年前在银行柜台办理业务的情形。 1:银行分配各个窗口给来办理业务的人 2:如果只有1个窗口开放(系统资源不足),大部分都得等 3:如果正在办理业务的突然说自己不办了(sleep),那他就去旁边再想想(等) 4:如果突然来了个VIP客户,可以强行插队 5:如果突然断电了(中断),都得等。。

    作者回复: 赞,太形象了

    共 4 条评论
    109
  • Q
    2018-12-25
    学习总结: * 上下文切换是什么? 上下文切换是对任务当前运行状态的暂存和恢复 * CPU为什么要进行上下文切换? 当多个进程竞争CPU的时候,CPU为了保证每个进程能公平被调度运行,采取了处理任务时间分片的机制,轮流处理多个进程,由于CPU处理速度非常快,在人类的感官上认为是并行处理,实际是"伪"并行,同一时间只有一个任务在运行处理。 * 上下文切换主要消耗什么资源,为什么说上下文切换次数过多不可取? 根据 Tsuna 的测试报告,每次上下文切换都需要几十纳秒到到微秒的CPU时间,这些时间对CPU来说,就好比人类对1分钟或10分钟的感觉概念。在分秒必争的计算机处理环境下,浪费太多时间在切换上,只能会降低真正处理任务的时间,表象上导致延时、排队、卡顿现象发生。 * 上下文切换分几种? 进程上下文切换、线程上下文切换、中断上下文切换 * 什么情况下会触发上下文切换? 系统调用、进程状态转换(运行、就绪、阻塞)、时间片耗尽、系统资源不足、sleep、优先级调度、硬件中断等 * 线程上下文切换和进程上下文切换的最大区别? 线程是调度的基本单位,进程是资源拥有的基本单位,同属一个进程的线程,发生上下文切换,只切换线程的私有数据,共享数据不变,因此速度非常快。 * 中断上下文切换,如何理解? 为了快速响应硬件的事件(如USB接入),中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件。而打断其它进程执行时,需要进行上下文切换。中断事件过多,会无谓的消耗CPU资源,导致进程处理时间延长。 * 有哪些减少上下文切换的技术用例? 数据库连接池(复用连接)、合理设置应用的最大进程,线程数、直接内存访问DMA、零拷贝技术
    展开

    作者回复: 👍

    共 3 条评论
    49
  • 炀
    2018-11-27
    cpu上下文切换就好比一个人有好多朋友要拜访,有的朋友房子大(进程),进进出出里三层外三层,有的朋友住帐篷(线程),就拉开帐篷聊聊天,有的朋友就隔着窗户说两句话打个照面路过(中断)

    作者回复: 😊很棒的比喻

    
    30
  • 地心引力
    2018-11-29
    进程调用系统调用,从用户态切换到内核态需要保存进程的上下文,而中断发生时,中断处理程序也是在内核态运行,但此时为什么就不需要保存进程的上下文呢,这种差别的本质原因是什么,望老师指教

    作者回复: 不是不保存进程上下文,而是不需要刷新虚拟内存这些用户空间的数据,但具体到内核中的状态肯定还是要刷新的

    共 2 条评论
    14
  • Juinn
    2019-01-23
    ring1和ring2是干嘛的?

    作者回复: 在Linux中没用到

    共 2 条评论
    7
  • glinuxer
    2018-11-27
    “其一,为了保证所有进程可以得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。”。 CFS 调度器没有时间片的概念了,叫做虚拟运行时间。

    作者回复: 👍感谢指出

    
    6
  • Bugsy
    2018-11-26
    因为内核态是cpu的一种特权模式,在这种模式下,内核可以访问系统资源(包括内存、cpu和其他IO设备),所以cpu上下文切换(包括进程上下文切换、线程上下文切换和中断切换)均是发生在内核态。 对于应用程序,在最开始都是运行在用户态,当程序中需要调用或者使用系统资源时(包括内存、cpu和其他io设备),由于受到安全性限制,他们只能能通过系统调用来运行部分内核的代码实现对系统资源的调用使用,这个过程就是从用户态陷入内核态的过程,在系统调用过程中一直是在同一个进程中实现。简短总结下,老师有没有其他资料可以推荐学习下。

    作者回复: 👍 后续推荐一些书籍

    
    6
  • Costar
    2019-08-15
    因此,进程的上下文切换就比系统调用时多了一步:在保存当前进程的内核状态和CPU寄存器之前,需要先把改进程的虚拟内存、栈等保持下来;而加载了下一进程的内核态后,还需要刷新进程的虚拟内存和用户栈。 ====>>>>>>> 以上表述,请问,进程间切换,需要把进程的虚拟内存、栈保存到哪里去? 我认为进程的虚拟内存、栈的数据本质是一直在 物理内存里的,进程切换,只要把 重新加载页表(映射关系)向MMU提供新的信息,进程的实际数据不需要动的。 当然CPU上下文还是要替换的。

    作者回复: 是的👍

    共 2 条评论
    4
  • 冷雨
    2019-03-30
    老师你好,比如一个用户进城里面有三个线程,在内核里面是同时创建三个对应的内核线程么?之前看资料说内核线程就是轻量级进程,所以对内核来说都是轻量级进程之间的切换带动不同用户进程或线程的切换?

    作者回复: 不是的,用户进程不会创建内核线程,内核线程是指一直都运行在内核态的任务

    共 3 条评论
    3