cpu-上下文切换

作者: Starlightskm | 来源:发表于2019-10-16 20:34 被阅读0次

    cpu-上下文切换

    前奏

    在每个进程任务运行之前,CPU需要知道任务从哪加载,又从哪里开始运行,也就是说,系统要实现帮进程任务设置好CPU寄存器和程序计数器

    • CPU寄存器

      • 容量小,速度极快的内存
    • 程序计数器

      • 存储CPU正在执行指令的位置

    所以,CPU寄存器和程序计数器,是CPU在运行任何任务之前必须依赖的环境,因此也被称作CPU上下文

    CPU上下文切换也就是把前一个任务的CPU上下文保存起来,然后加载新任务的向下文到这些寄存器和程序计数器

    image.png

    CPU上下文切换场景分类

    根据任务的不同,CPU上下文切换分为如下的几类:

    • 进程上下文切换

    • 线程上下文切换

    • 中断上下文切换

    进程上下文切换

    Linux按照特权等级,把进程分为内核空间用户空间

    内核空间:

    - Ring0:具有最高权限,可以直接访问所有资源
    

    用户空间

    - Ring3: 只能访问受限的资源,不能直接访问内存等硬件设备,必须用过系统调用陷入内核,才能访问这些特权资源
    
    image.png

    用户态到内核态的转变需要系统调用来完成,

    系统调用结束后,CPU 寄存器需要恢复原来保存的用户态,然后在切换到用户空间,继续运行进程。一次系统调用的过程其实发生了两次上下文切换。

    进程上下文切换和 系统调用的上下文切换

    进程上下文切换: 是从一个进程切换到另一个进程运行

    系统调用的上下文切换: 一直是同一个进程在运行,系统调用过程通常称为特权模式切换,而不是上下文切换

    区别如下:

    - 进程由内核来管理和调度的,进程的切换只能发生在内核态
    
    - 进程上下文切换比系统调用多了一个过程
    

    Linux通过TLB来管理虚拟内存到物理内存的映射关系,当虚拟内存更新之后TLB也需要刷新,内存的访问也会随之变慢。

    进程切换时才需要上下文切换,Linux为每个CPU都维护了一个就绪队列,将活跃进程按照优先级和等待CPU的时间进行排序,然后选择最需要CPU的进程,也就是最高优先级和等菜CPU时间最长的进程来运行

    进程在什么时候会调度到CPU上运行

    • 为了保证所有的进程可以公平调度,CPU时间被划分成一段段的时间片,这些时间片灾备轮流分配给各个进程,这样,当某个进程的时间片被耗尽,就会被系统挂起,切换到其他正在等待CPU的进程运行

    • 进程在系统资源不足时,要等到资源买足后才可以运行,这个时候进程也会被挂起,并有系统调度大其他进程运行

    • 当进程通过睡眠函数sleep这样的方法将自己主动挂起,自然也会重新调度

    -当优先级更高的进程运行时,为了保证高优先级的进程运行,当前的进程会被挂起,由高优先级的进程来运行

    • 当发生硬件中断时,CPU上的进程会被中断挂起,转而执行内核中的中断服务程序

    线程上下文切换

    线程是调度的基本单位,晋城市资源拥有的基本单位。

    所谓的内核中的任务调度,实际上调度对象是线程,而进程只是给线程提供了虚拟内存,全局变量等资源。

    • 当进程只有一个线程时,可以认为进程就等于线程

    • 当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换的时候是不需要修改的

    • 线程也有自己的私有数据,比如栈和寄存器等,浙西在上下文切换时也是需要保存的

    线程上下文切换的情况:

    - 前后两个线程属于不同的进程
    
    - 前后两个线程属于同一个进程,切换的数据只有线程的不共享的数据
    
    - 多线程对于多进程会消耗更少的资源,所以多线程是替代多进程的一个优势
    

    中断上下文切换

    为了快速响应硬件时间,中断会打断进程的正常调度和执行,转而调度中断程序,响应设备事件,而中断执行过程中会挂起当前正常的进程。

    • 为了快速响应硬件事件,中断会打断进程的正常调度和执行

    • 对于同一个CPU来说,中断处理比进程拥有更高的优先级

    小结

    • CPU上下文切换是保证Linux正常工作的核心功能之一,一般不用特别关注

    • 如果上下文切换过多,会将CPU时间消耗在寄存器内核栈以及虚拟内存等数据的保存和恢复上

    实战上下文切换

    查看整体的CPU上下文切换

    
    [root@www ~]# vmstat 5
    
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
    
     r b swpd free buff cache si so bi bo in cs us sy id wa st
    
     3 0 0 80144 140508 1143972 0 0 16 25 1 1 1 0 99 0 0
    
    

    其中:

    • cs:每秒上下文切换次数

    • in:每秒中断次数

    • r:就绪队列长度

    • b: 不可睡眠状态的进程数

    查看每个进程的CPU详细上下文切换

    
    [root@www ~]# pidstat -w 5
    
    Linux 3.10.0-862.el7.x86_64 (www.cropy.cn) 10/16/19 _x86_64_ (1 CPU)
    
    16:11:34 UID PID cswch/s nvcswch/s Command
    
    16:11:39 0 1 0.80 0.00 systemd
    
    16:11:39 0 3 1.40 0.00 ksoftirqd/0
    
    16:11:39 0 9 28.74 0.00 rcu_sched
    
    16:11:39 0 11 0.40 0.00 watchdog/0
    
    16:11:39 0 29 0.20 0.00 khugepaged
    
    

    需要记住的参数如下:

    • cswch:自愿上下文切换,这个参数是指进程无法获取所需资源导致的上下文切换,比如:IO,内存等资源不足的时候会发生自愿上下文切换

    • nvcswch: 非自愿上下文切换,这个参数表示进程时间片已到等原因被系统强制调度,进而发生上下文切换。比如:大量进程抢占CPU的时候会发生非自愿上下文切换

    案例分析

    环境需求

    • centos7

    • sysstat: 1.15以上

    • sysbench

    • root权限

    实战测试

    • 第一个终端执行如下操作
    
    [root@www ~]# sysbench --threads=10 --max-time=300 threads run      #开启10个进程的五分钟的基准测试,模拟多线程切换
    
    
    • 第二个终端执行如下
    
    [root@www ~]# vmstat 1
    
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
    
     r b swpd free buff cache si so bi bo in cs us sy id wa st
    
    10 0 0 180128 122484 1054324 0 0 12 0 1112 1249403 17 83 0 0 0
    
     7 0 0 180128 122484 1054336 0 0 4 0 1097 1262657 16 84 0 0 0
    
     8 0 0 180128 122484 1054340 0 0 0 0 1089 1224114 18 82 0 0 0
    
     8 0 0 180112 122484 1054340 0 0 0 0 1116 1255382 19 81 0 0 0
    
     8 0 0 180096 122488 1054340 0 0 36 16 1149 1249025 18 82 0 0 0
    
    

    发现如下的问题

    • r:就绪队列在长度达到8

    • us和sy:两列加起来到了100,sy在84左右,证明CPU被内核占用了

    • in: 中断也达到了1000以上

    综合上面的三个点,可以发现CPU的使用率很高

    • 然后再开一个终端,执行如下命令
    
    [root@www ~]# pidstat -w -u 1
    Linux 3.10.0-862.el7.x86_64 (www.cropy.cn) 10/16/19 _x86_64_ (1 CPU)
    
    16:42:08 UID PID %usr %system %guest %wait %CPU CPU Command
    
    16:42:09 0 22937 0.00 1.00 0.00 0.00 1.00 0 barad_agent
    
    16:42:09 0 31092 17.00 83.00 0.00 0.00 100.00 0 sysbench
    
    16:42:08 UID PID cswch/s nvcswch/s Command
    
    16:42:09 0 1 1.00 0.00 systemd
    
    16:42:09 0 3 1.00 0.00 ksoftirqd/0
    
    16:42:09 0 9 32.00 0.00 rcu_sched
    
    16:42:09 0 9921 1.00 0.00 supervisord
    
    16:42:09 0 10617 1.00 0.00 YDLive
    
    16:42:09 0 16286 2.00 0.00 IntelliJIDEALic
    
    16:42:09 1000 17350 2.00 0.00 sshd
    
    16:42:09 0 22936 3.00 0.00 barad_agent
    
    16:42:09 0 28412 1.00 0.00 kworker/0:1
    
    16:42:09 1003 28963 3.00 0.00 tmux
    
    16:42:09 0 30007 11.00 0.00 kworker/0:0
    
    16:42:09 0 30560 1.00 0.00 vmstat
    
    16:42:09 0 31225 6.00 0.00 ntpdate
    
    16:42:09 0 31226 2.00 0.00 grep
    
    16:42:09 0 31241 1.00 0.00 pidstat
    
    

    可以发现CPU使用过高是sysbench导致的,pidstat -wt 可以分析到线程级别

    也可以如下的方式去查看:

    
    **[root@www ~]# watch -d cat /proc/interrupts **
    
    

    相关文章

      网友评论

        本文标题:cpu-上下文切换

        本文链接:https://www.haomeiwen.com/subject/urfpmctx.html