软中断
软中断
1 | top -H -p XX 1 / pidstat -wut -p XX 1 #那个线程占用CPU |
当iowait升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从ps或者top命令的输出中,你可以发现它们都处于D状态,也就是不可中断状态(Uninterruptible Sleep)。
进程状态有哪几种:
R 是Running 或 Runnable 的缩写,表示进程CPU的就绪队列中,正在运行或者正在等待运行
D 是Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程中不允许被其他进程或中断打断
Z 是Zombie的缩写,也就是可中断状态的睡眠,表示进程因为等待某个事件而被系统挂起,当进程等待的时间发生时,它会被唤醒并进入R状态
I 是idle的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上,前面说了,硬件交互导致的不可中断进程D表示,但对某些内核线程会导致平均负载升高,I状态的进程却不会。
T或者t 也就是Stopped和Traced的缩写,表示进程处于暂停或者跟踪状态
向一个进程发送SIGSTOP信号,它就会因为响应这个信号变成暂停状态(Stopped);再向它发送SIGCONF信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你用fg命令,恢复到前台运行)
X 也是Dead的缩写,表示进程已经消亡,所以你不会再top或者ps命令中看到它
总结:
不可中断状态,表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其他进程或中断
打断这个进程。进程长时间处于不可中断状态,通常表示系统I/O性能问题
僵尸进程表示进程已经退出,但它的父进程还没有回收子进程占用的资源。短暂的僵尸状态我们通常不必理会
但进程长时间处于僵尸状态,就应该注意了,可能有应用程序没有正常处理子进程的退出
总结:分析系统等待I/O的CPU使用率(也就是iowait%)升高的情况
iowait高并不一定代码I/O有性能瓶颈。当然系统中只有I/O类型的进程在运行时,iowait也会很高
但是实际上,磁盘的读写远没有达到性能瓶颈的程度
因此,碰到iowait升高时,需要先用dstat、pidstat等工具,确认是不是磁盘I/O问题,然后找是
那些进程导致了I/O升高
等待I/O的进程一般是不可中断状态,所以用ps命令找到的D状态(即不可中断状态)的进程,多为
可以进程
当一个进程执行到最后成僵尸进程,就不能用strace,因为当前进程已经不存在了
用ps查看该进程是D状态是可以用strace进行追踪,否则用另外一种方法:
perf record -g(执行15s)停止,用perf report 进行查看分析
1 | --- |
1、linux并发(任务并行)的实质:linux作为一个多任务操作系统,将每个CPU的时间划分为很短站的时间片,再通过调度器轮流分配给各个任务使用,再通过调度器轮流分配给各个任务使用
2、CPU的维护,通过实现定义的节拍率(内核用赫兹HZ标示),触发时间判断(全局变量jiffes)记录。
3、节拍率的内核态运行,属于内核空间节拍率:用户空间节拍率(USER_HZ)是一个固定值
4、/proc/stat 提供的就是系统的CPU核任务统计系统信息: /proc/[pid]/stat展示进程的CPU核任务统计信息
5、CPU的使用率={1-(idle_time/total_cpu_time)}/sample_ti
6、性能分析工具给出的都是间隔一段时间的平均CPU使用率,所以要注意间隔的设置。top默认为3s,ps使用的是进程运行时间
7、top、vmstat、mpstat等命令关于CPU性能相关指标的含义
8、pidstat命令指标的含义
9、perf以前用到的一堆[n]trace分析工具,perf的直观易用,这是今天最大的收获,作为dba对数据库的分析很有用的
perf top、perf record、perf report对进程进行跟踪分析其调用perf top -g -p
10、今天用测试工具:ab (apache-utils centos安装包)
如果碰到不好解释的CPU问题时,比如现象:
通过top观察CPU使用率很高,但是看下面的进程的CPU使用率好像很正常,通过pidstat命令查看cpu也很正常。但通过top查看task数量不正常,处于R状态的进程是可疑点。
首先要想到可能是短时间的应用导致的问题,如下面的两个:
(1)应用里直接调用了其他二进制程序,这些程序通常运行时间比较短,通过top等工具发现不了
(2)应用本身在不停地崩溃重启,而启动过程的资源初始化,很可能会占用很多CPU资源
对于这类进程就需要 pstree 或execsnoop命令查找父进程,再从父进程的应用入手,找原因。
我实战的问题:
(1)centos的系统,发现通过 yum install pstress命令或其他命令,总是说没有匹配的软件包,这个很头疼
①pstress装不上可以尝试 yum install psmisc
②execsnoop这个命令我没有装上,想请教下老师如何解决这种yum install命令报没有匹配包的情况
(2)然后就是通过perf命令只能看到十六进制符号,看不到具体函数名的问题,这个可以使用上篇文章中我的留言的方法,我在copy一份,供大家参考
分析:当没有看到函数名,只看到十六进制时,说明perf无法找到待分析进程所依赖的库。
解决办法:
在容器外面把分析记录保存,到容器里面查看结果
操作:
(1)在centos系统上运行 perf record -g ,执行一会儿按ctrl+c停止
(2)把生成的perf.data(通常文件生成在命令执行的当前目录下,当然可以通过find | grep perf.data或 find / -name perf.data查看路径)文件拷贝到容器里面分析:
1 | --- |
cpu上下文切换分为:进程上下文切换,线程上线文切换和中断上下文切换
1、进程上线文切换
Linux安装特权等级,把进程的运行空间分为内核空间和用户空间
内核空间具有最高权限,可以直接访问所有资源
用户空间只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统调用陷入到内核中才能访问这些特权资源
换个角度看,也就是说,进程既可以在用户空间运行,也可以在内核空间运行。进程在用户空间运行时,被称为进程的用户态,
而陷入内核空间的时候,被称为进程的内核态
从用户态和内核态的转变,需要通过系统调用来完成,比如:当我们查看文件内容时,就需要多次系统调用来完成,首先调用
open()打开文件,然后调用read()读取文件内容,并调用write()将内容写到标准输出,最后调用close()关闭文件
CPU寄存器里原来用户态的指令的位置,需要先保存起来,接着,为了执行内核态代码,CPU寄存器需要更新为内核态指令的新位置
,最后才跳转到内核态运行内核任务
而系统调用结束后,CPU寄存器需要恢复原来保存的用户态,然后再切到用户空间,继续运行进程,所以,一次系统调用的过程,其实时发生了两次cpu上线文切换,不过需要注意的是,系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也不会切换进程,这跟我们通常所说的进程上线文切换时不一样的
(1) 进程上线文切换,是指一个进程切换到另一个进程运行
(2) 而系统调用过程中一直是同一个进程在运行
所以,系统调用过程通常为特权模式切换,而不是上下文切换。但实际上,系统调用过程中,CPU的上线文切换时无法避免的
进程上下文切换跟系统调用有什么区别呢?
首先,进程是由内核来管理和调度的,进程的切换只发生在内核。所以,进程的上下问不仅包括了虚拟内存、栈、全局变量等用户空间的资源,还包括了内核堆栈、寄存器等内核空间的状态
因此,进程的上下问切换就比系统调用时多了一步:在保存当前进程的内核状态和CPU寄存器之前,需要先把该进程的虚拟内存、栈等保存下来;而加载了下一个进程的内核后。还需要新进程的虚拟内存和用户栈
根据Tsuna测试报告,每次上下文切换都需要几十纳秒到数微妙的CPU的时间.这个时间还是相当可观的,特别是在进程上下文切换次数较多的情况下,很容易导致CPU将大量时间耗费在寄存器、内核栈以及虚拟内存等资源的保存和恢复上,进而大大缩短了真正运行进程的时间,这也正是上一节中我们所讲的,导致平均负载升高的一个重要因素
另外 Linux是通过TLB(Translation Lookaside) 来管理虚拟内存到物理内存的映射关系。当虚拟内存更新后,TLB也需要刷新,内存的访问也会随之变慢,特别是在多处理器系统上,缓存是被多个处理器共享的,刷新缓存不仅会影响当前处理器的进程,还会影响共享缓存的其他处理器的进程
进程在什么时候才会被调度到CPU上运行呢?
最容易想到的一个时机,就是进程执行完终止了,它之前使用的CPU会释放出来,这个时候再从就绪队列,拿一个新的进程过来运行,其实还有很多其他场景,也会触发进程调度,如下:
(1) 为了保证所有进程可以得到公平调度,CPU时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。这样当某个进程的时间片耗尽了,就会被系统挂起,切到其它正在等待CPU的进程运行
(2) 进程在系统资源不足(比如内存不足)时,要等到资源满足后才可以运行,这个时候进程也会被挂起,并由系统调度其他进程运行。
(3) 当进程通过睡眠函数sleep这样的方法将自己主动挂起时,自然也会重新调度
(4) 当有优先级更高的进程运行时,为了保证高优先级进程的运行,当前进程会被挂起,由高优先级进程运行
最后一个,发生硬件中断时,CPU上的进程会被中断挂起,转而执行内核中的中断服务程序
2、线程上线文切换
线程和进程最大区别在于,线程是调度的基本单位,而进程则是资源拥有的基本单位。说白了,所谓内核中的任务调度,实际上的调度对象是线程;而进程只是给线程提供了虚拟内存、全局变量等资源。所以对于线程和进程,我们可以这样理解:
(1) 当进程只有一个线程时,可以认为进程就等于线程
(2) 当进程拥有多个线程时,这些线程会共享
3、中断上下文切换
为了快速响应硬件的事件,中断处理会打断进程的正常调度和执行,转而调用中断处理程序,响应设备事件。而在打断其他进程时,就需要将进程当前的状态保存下来,这样在中断结束后,进程仍然可以从原来的状态恢复运行。
跟进程上下文不同,中断上下文切换并不涉及到进程的用户态。所以即便中断过程打断一个正处在用户态的进程,也不需要保存和恢复这个进程的虚拟内存、全局变量等用户态资源。中断上下文,其实只包括内核态中断服务程序执行所必须的状态,包括CPU寄存器、内核堆栈和硬件中断参数等。
对同一个CPU来说,中断处理比进程拥有更高的优先级,所以中断上下文切换并不会与进程上下文切换同时发生。同样道理,由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。
另外,跟进程上下文切换一样,中断上下文切换也需要消耗CPU,切换次数过多也会消耗大量CPU,甚至严重降低系统的整体性能,所以,当你发现中断次数过多时,就需要注意去排查它是否会给你的系统带来严重的性能问题
场景:
cpu上下文切换,是保证Linux系统正常工作的核心功能之一,一般情况下不需要我们特别关注
但过多的上下文切换,会把CPU时间消耗在寄存器、内核栈以及虚拟内存等数据的保存和恢复上,从而缩短进程真正运行的时间,导致系统的整体性能答复下降
总结:
1、多任务竞争CPU,CPU变换任务时进行cpu上下文切换(context switch)。CPU执行任务4中方式:进程、线程、或者硬件通过触发信号导致cpu中断的调用
2、当切换任务的时候,需要记得任务当前的状态和获取下一任务信息和地址(指针),这就是上下文的内容,因此,上下文是指某一时间CPU寄存器(CPU register)和程序计数器(PC)的内容,广义上还包括内存中进程的虚拟地址映射信息
3、上下文切换的过程
(1) 记录当前任务的上下文(即寄存器和计算器等所有的状态)
(2) 找到新任务的上下文并加载
(3) 切换到新任务的程序计算器位置,恢复期任务
4、根据任务的执行形式,相互的下上文切换,有进程上下文切换、线程上下文切换以及中断上下文切换三类
5、进程和线程区别:进程是资源分配合执行的基本单位;线程是任务调度和运行的基本单位。线程没有资源,进程给指针提供虚拟内存、栈和变量等共享资源,而线程可以共享进程的资源
6、进程上线文切换:是指从一个进程切换到另一个进程。
(1) 进程运行态为内核运行态和进程运行态,内核空间态资源包括内核的堆栈、寄存器等;用户空间态资源包括虚拟内存、栈、变量、正文和数据等
(2) 系统调用(软中断)在内核态完成的,需要进行2次CPU上下文切换(用户空间->内核空间->用户空间),不涉及用户资源,也不会切换进程
(3) 进程是由内核来管理和调度的,进程的切换只能发生在内核态,所以,进程的上下文切换不仅包括了用户空间的资源,也包括内核空间的资源
(4) 进程的上下文切换过程:
(a) 接收到切换信号,挂起进程,记录当前进程虚拟内存、栈等资源存储
(b) 将这个进程在CPU中的上下文状态存储起来
(c) 然后在内存中检索下一个进程的上下文
(d) 并将其加载到CPU的寄存器中恢复
(e) 还需要刷新新进程的虚拟内存和用户栈
(f) 最后跳转到程序计数器所指向的位置(即跳转搭配进程被中断时的代码行),以恢复改进程
(5) 下列将会触发进程上下文切换的场景:
(a) 根据调度策略,将CPU时间划分为对应的时间片,当时间片耗尽时,当前进程必须挂起
(b) 资源不足的,在获取到足够资源之前进程挂起
(c) 进程sleep挂起进程
(d) 高优先级进程导致当前进度挂起
(e) 硬件中断,导致当前进程挂起
7、线程上下文切换
(1) 不通进程之前的线程上下文切换,其过程和进程上下文切换大致相同
(2) 进程内部的线程上下文切换,不需要切换进程用户资源,只需要切换线程私有的数据和寄存器等,这会比进程上下文进程切换消耗的资源少,所以多线程相比多线程优势
8、中断上下文切换
快速响应硬件的事件,中断处理会打断进程的正常调度和执行,同一CPU内,硬件中断优先级高于进程。切换过程类似于系统调用,不涉及到用户运行态资源,但大量的中断上下文切换同样可能引发性能问题
备注:系统调用属于上下文切换,分别是CPU用来存储指令和下一条要执行指令的寄存器
1 | --- |
查看系统上下文切换情况:系统分析工具vmstat(vmstat是只给出了系统总体上下文切换情况,要想查看每个进程的详细情况,要向)
cs(context switch)是每秒上下文切换的次数。
in(interrupt)则是每秒中断的次数。
r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
b(Blocked)则是处于不可中断睡眠状态的进程数。
###pidstat是查看每个进程上下文切换情况:(-w)每隔5秒输出1组数据
解释:一个是 cswch ,表示每秒自愿上下文切换(voluntary context switches)的次数,
另一个则是 nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。
所谓自愿上下文切换,是指进程无法获取所需资源,导致的上下文切换。比如说, I/O、内存等系统资源不足时,就会发生自愿上下文切换。
而非自愿上下文切换,则是指进程由于时间片已到等原因,被系统强制调度,进而发生的上下文切换。比如说,大量进程都在争抢 CPU 时,就容易发生非自愿上下文切换。
---