1.什么是CPU上下文切换?

linux是一个多任务操作系统,它支持远大于CPU数量的任务同时运行,当然这些任务实际上并不是真的同时在运行,而是因为系统在很短的时间内,将CPU轮流分配给它们,造成多任务同时运行的错觉

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

CPU寄存器,是CPU内置的容量小,但是速度极快的内存。而程序计数器,则是用来存储CPU正在执行的指令位置,或者即将执行的下一条指令位置。它们都是CPU在运行任何任务前,必须依赖的环境,因此也被叫做CPU上下文

CPU的上下文切换就是先把前一个任务的CPU上下文(也就是CPU寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。

2.上下文切换的类型?(按照任务不同区分)

(1).进程上下文切换(不同进程之间上下文切换)

(2).线程上下文切换,包括同一个进程下线程上下文切换,不同进程下线程上下文切换

(3).中断上下文切换,即中断程序导致的上下文切换

(4).自愿上下文切换(cswch),是指进程无法获取所需资源,导致的上下文切换

(5).非自愿上下文切换(nvcswch),是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换,比如大量进程都在争抢CPU时,就容易发生非自愿上下文切换

3.Linux中如何查看上下文切换?

vmstat中cs, 表示每秒上下文切换的次数

pidstat(pidstat -w 5),查看每个进程的上下文切换情况,cswch表示每秒自愿上下文切换次数,nvcswch表示每秒非自愿上下文切换的次数

4.上下文切换的场景:

(1).进程上下文切换场景:

1.为了保证所有进程得到公平调度,CPU时间被划分成一段段的时间片,这些时间片再被轮流分配给各个进程,这样,当某个进程的时间片耗尽时,就会被系统挂起,切换到其他正在等待CPU的进程运行(即进程由于时间片已到,导致的进程上下文切换)

2.进程的系统资源不足(比如内存不足时),要等到资源满足后才可以运行,这个时候进程会被挂起,并由系统调度其他进程运行

3.进程通过睡眠函数sleep将自己主动挂起,自然也会重新调度

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

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

进程上下文切换次数较多的情况下,很容易导致CPU将大量时间耗费在寄存器,内核栈以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间。这也是导致平均负载升高的一个重要因素

(2).线程上下文切换:

线程与进程的最大区别在于,线程是调度的基本单位,而进程则是资源拥有的基本单位。所谓内核中的任务调度,调度对象是线程,而不是进程,进程只是给线程提供了虚拟内存,全局变量等资源。对于进程和线程可以

这么理解:

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

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

3.线程也有自己的私有数据,比如栈和寄存器,这些在上下文切换时也是需要保存的。

线程的上下文切换就可以分为两种情况:

1.前后两个线程属于不同进程,此时,因为资源不共享,所以切换过程就跟进程上下文切换一样

2.前后两个线程属于同一个进程,因为虚拟内存是共享的,所以在切换时,虚拟内存这些资源就保存不动,只需要切换线程的私有数据,寄存器等不共享数据

虽然同为上下文切换,但同进程内的上下文切换,要比多进程间的切换消耗更少的资源,而这也是多线程代替多进程的一个优势。

5.上下文切换升高导致的性能问题(案例场景):

1.准备工作:安装sysbench,准备linux环境,开启3个终端,切换root用户运行

2.操作步骤:

1.在第一个终端运行sysbench,模拟多线程调度的瓶颈:

# 以 10 个线程运行 5 分钟的基准测试,模拟多线程切换的问题

$ sysbench --threads=10 --max-time=300 threads run

    2.在第二个终端运行vmstat,观察上下文切换的情况:

# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
       $ 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
       6 0 0 6487428 118240 1292772 0 0 0 0 9019 1398830 16 84 0 0 0
       8 0 0 6487428 118240 1292772 0 0 0 0 10191 1392312 16 84 0 0 0

从vmstat的输出可以发现,cs列的上下文切换次数上升到139万,同时,注意观察其他几个指标:

(1).R列,就绪队列的长度已经到了8,远远超过CPU个数,所以肯定会有大量的CPU竞争

(2).us和sy,这两列的CPU使用率加起来上升到了100%,其中系统CPU使用率,也就是sy列高达84%,说明CPU主要被内核占用

(3).in列:中断次数也上升到了1万左右,说明中断处理也是个潜在的问题

综合这几个指标,可以知道,系统的就绪队列过长,也就是正在运行和等待CPU的进程数过多,导致了大量的上下文切换,而上下文切换又导致了系统CPU使用率升高。

那么,到底是什么进程导致了这些问题呢?

3.继续分析,在第三个终端再用pidstat来看一下,CPU和进程上下文切换的情况:  

# 每隔 1 秒输出 1 组数据(需要 Ctrl+C 才结束)
# -w 参数表示输出进程切换指标,而 -u 参数则表示输出 CPU 使用指标
$ pidstat -w -u 1
08:06:33 UID PID %usr %system %guest %wait %CPU CPU Command
08:06:34 0 10488 30.00 100.00 0.00 0.00 100.00 0 sysbench
08:06:34 0 26326 0.00 1.00 0.00 0.00 1.00 0 kworker/u4:2

08:06:33 UID PID cswch/s nvcswch/s Command
08:06:34 0 8 11.00 0.00 rcu_sched
08:06:34 0 16 1.00 0.00 ksoftirqd/1
08:06:34 0 471 1.00 0.00 hv_balloon
08:06:34 0 1230 1.00 0.00 iscsid
08:06:34 0 4089 1.00 0.00 kworker/1:5
08:06:34 0 4333 1.00 0.00 kworker/0:3
08:06:34 0 10499 1.00 224.00 pidstat
08:06:34 0 26326 236.00 0.00 kworker/u4:2
08:06:34 1000 26784 223.00 0.00 sshd

从pidstat的输出可以发现,CPU使用率升高果然是sysbench导致的,它的CPU使用率高达100%,但上下文切换则来自其他进程。

pidstat输出的上下文切换次数,加起来也就几百,比vmstat的139W明显小了太多。

通过运行man pidstat,发现pidstat默认显示的是进程的指标数据,加上 -t参数后,才会输出线程的指标:

# 每隔 1 秒输出一组数据(需要 Ctrl+C 才结束)
   # -wt 参数表示输出线程的上下文切换指标
   $ pidstat -wt 1
   08:14:05 UID TGID TID cswch/s nvcswch/s Command
   ...
   08:14:05 0 10551 - 6.00 0.00 sysbench
   08:14:05 0 - 10551 6.00 0.00 |__sysbench
   08:14:05 0 - 10552 18911.00 103740.00 |__sysbench
   08:14:05 0 - 10553 18915.00 100955.00 |__sysbench
   08:14:05 0 - 10554 18827.00 103954.00 |__sysbench
   ...

从这次pidstat的输出中,虽然sysbench进程的上下文切换次数不多,但是它的子进程上下文切换次数却很多。看来,上下文切换罪魁祸首,还是过多的sysbench线程。

4.接下来,继续分析中断次数上升的根源,既然是中断,我们都知道,它只发生在内核态,而pidstat只是一个进程的性能分析工具,并不能提供任何关于中断的信息,怎样才能知道中断发生的类型呢?

从/proc/interrupts这个只读文件读取,/proc实际上是Linux的一个虚拟文件系统,用于内核空间与用户空间之间的通信。/proc/interrupts就是这种通信机制的一部分,提供了一个只读的中断使用情况

在第三个终端,运行下面的命令,查看中断的变化情况:

# -d 参数表示高亮显示变化的区域
    $ watch -d cat /proc/interrupts
    CPU0 CPU1
     ...
    RES: 2450431 5279697 Rescheduling interrupts
    ...

观察一段时间,发现变化速度最快的是重调度中断,这个中断类型表示,唤醒空闲状态的CPU来调度新的任务运行。这是多处理器系统(SMP)中,调度器用来分散任务到不同CPU的机制,通常也被称为

处理器间中断。所以这里的中断升高还是因为多任务的调度问题,跟前面的上下文切换次数的分析结果是一致的。

这次通过一个sysbench的案例,讲解了上下文切换问题的分析思路,碰到上下文切换次数过多的问题时,可以借助vmstat,pidstat和/proc/interrupts等工具,来辅助排查性能问题的根源。

总结:

上下文切换指标:

(1).上下文切换次数取决于系统本身的CPU性能,如果系统的上下文切换次数比较稳定,那么从数百到1万以内都是正常的

(2).当上下文切换次数超过1万次,或者切换次数出现数量级增长时,就很可能已经出现了性能问题

同一个进程下线程上下文切换,因为共享虚拟内存,切换过程中,虚拟内存这些资源保持不变,只需要切换线程的私有数据,寄存器等不共享的数据。(多线程代替多进程)

自愿上下文切换变多了,说明进程都在等待资源,有可能发生IO等其他问题

非自愿上下文切换变多了,说明进程都在被强制调度,都在争抢CPU,说明CPU的确成了瓶颈

中断上下文切换变多了,说明CPU被中断处理程序占用,需要通过查看 /proc/interrupts文件分析具体的中断类型

关于linux系统CPU篇--->上下文切换的更多相关文章

  1. 关于linux系统CPU篇--->不容易发现的占用CPU较高进程

    1.系统的CPU使用率,不仅包括进程用户态和内核态的运行,还包括中断处理,等待IO以及内核线程等等.所以,当你发现系统的CPU使用率很高的时候,不一定能找到相对应的高CPU使用率的进程 2.案例分析, ...

  2. 关于linux系统CPU篇--->CPU使用率升高

    1.CPU使用率为单位时间内CPU使用情况的统计,以百分比的方式展示. LINUX作为一个多任务操作系统,将每个CPU的时间划分为很短的时间片,再通过调度器轮流分配给各个任务使用,因此造成多任务同时运 ...

  3. 关于linux系统CPU篇--->平均负载

    1.什么是平均负载?(load average) 平均负载是指单位时间内平均活跃进程数,包括可运行状态的进程数,以及不可中断状态的进程(如等待IO,等待硬件设备响应) 2.如何查看平均负载? 使用to ...

  4. Linux系统cpu 100%修复案例

    Linux系统cpu 100%修复案例 ​阿里云技术支持团队:完颜镇江 案例背景: Linux主机连续三天CPU% 处理思路: 1.  登录服务器查看/var/log/messages+/var/lo ...

  5. linux系统CPU,内存,磁盘,网络流量监控脚本

    前序 1,#cat /proc/stat/ 信息包含了所有CPU活动的信息,该文件中的所有值都是从系统启动开始累积到当前时刻 2,#vmstat –s 或者#vmstat 虚拟内存统计 3, #cat ...

  6. Linux系统CPU相关信息查询

    Linux系统CPU相关信息查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.lscpu常用参数介绍 1>.查看帮助信息 [root@node105 ~]# lscpu ...

  7. C/C++获取Linux系统CPU和内存及硬盘使用情况

    需求分析: 不使用Top  df  free 等命令,利用C/C++获取Linux系统CPU和内存及硬盘使用情况 实现: //通过获取/proc/stat (CPU)和/proc/meminfo(内存 ...

  8. Java获取Linux系统cpu使用率

    原文:http://www.open-open.com/code/view/1426152165201 import java.io.BufferedReader; import java.io.Fi ...

  9. linux系统cpu和内存占用率

    1.top 使用权限:所有使用者 使用方式:top [-] [d delay] [q] [c] [S] [s] [i] [n] [b] 说明:即时显示process的动态 d :改变显示的更新速度,或 ...

随机推荐

  1. 使对象可以像数组一样进行foreach循环,要求属性必须是私有

    class myIterator implements Iterator { private $var = array(1, 2, 3, 4, 5); public function __constr ...

  2. 听说尤雨溪在开发vue4.0?是谁煽动了前端圈的焦虑情绪

    导火索因P图而起 今天前端圈里被一张P图搞得好热闹,最初只是QQ群里一个冒名尤雨溪的前端网友发了一句调侃的话,原话截图如下: 看完觉得好搞笑,说尤雨溪在开发vue4.0,有谁学不动了,就给他发10块钱 ...

  3. java_基础_异常

    之前只是了解的最基础的异常形式,没有过多的深入 今天因为一些原因了解了一下 下面来说说异常的几种形式 1.try-catch语句块 代码示例 class test{ public static voi ...

  4. 关于反射和JVM的整理

  5. 阿里云Ubuntu 18.04安装图形界面

    #!/bin/bash #更新软件库 apt-get update #升级软件 apt-get upgrade #安装ubuntu桌面系统 apt-get install ubuntu-desktop

  6. ASO关键词优化技巧:如何充分利用热搜榜与相关热点?

    ASO关键词优化对提高市场曝光率.增加APP下载量有着至关重要的作用.那如何充分利用热搜榜与相关热点来进行ASO优化呢?   一.产品定位   因为此文主要是讲优化APP关键词的,所以产品定位这一块就 ...

  7. odoo定时发送邮件

    采购订单延迟或者存在部分到货的情况,定时发送邮件给相关人员 包含,采购订单明细,订单数量,已到货数量,未到货数量 <?xml version="1.0" encoding=& ...

  8. JavaScript 中 return,return true,return false

    1.return: ①return + 表达式,调用函数,并返回表达式的值 ②return,终止函数 ③当代码执行到return语句时,函数返回一个结果就结束运行了,return后面的语句根本不会执行 ...

  9. LINQ交集/并集/差集/去重

    using System.Linq; List<string> ListA = new List<string>(); List<string> ListB = n ...

  10. Visual Stdio 2017增加SVN支持

    实验目的 当前公司项目源码文档等内容都保存在svn上,现在是用着小乌龟在文件浏览状态中去检出和提交等操作,没有集成到vs2017中来,比较麻烦.现在要把vs2017增加svn支持,希望可以直接在IDE ...