Last Updated on

正文

熟悉linux系统,是所有系统运维的基础,但系统也不是那么好理解的,大多运维也只是停留在会用的程度上,虽然要想深入研究系统内核等很难,但起码多了解一层,多一些更加深入的理解,就会带来不一样的思路。往往也就比别人更厉害一点点。

下面就详细讲讲系统中的CPU状态信息,这些状态信息表示了什么意思,可以帮助我们更好的理解CPU状态。

正文

在日常运维中,关于CPU的就是,如果监控CPU使用情况,CPU压力过高,如何排查问题,如果解决。

了解CPU情况,一般,则直接使用top命令,可以查看到cpu的当前状态:

在top命令中,关于cpu的,有两个数据:load average%Cpu(s)

load average

顾名思义,平均负载。显示的数据代表最近1分钟、5分钟和15分钟的系统平均负载。

平均负载:

平均负载:在特定时间间隔内运行队列中(在CPU上运行或者等待运行多少进程)的平均进程数。如果一个进程满足以下条件则其就会位于运行队列中:

  • 它没有在等待I/O操作的结果
  • 它没有主动进入等待状态(也就是没有调用’wait’)
  • 没有被停止(例如:等待终止)

在Linux中,进程分为三种状态:

  • blocked process:阻塞的进程
  • runnable process:可运行的进程
  • running process:正在运行的进程

当进程阻塞时,进程会等待I/O设备的数据或者系统调用,进程可运行状态时,它处在一个运行队列run queue中,与其他可运行进程争夺CPU时间。 系统的load是指正在运行running process和准备好运行runnable process的进程的总数。比如现在系统有2个正在运行的进程,3个可运行进程,那么系统的load就是5。load average就是一定时间内的load数量

通过平均负载数据来判断系统CPU负载情况,并不是数据越小越好,越大越差。

具体的判断,这与CPU的核数有关,1核cpu,则此负载数据,满载为1,但完全满载说明已经满负荷了,正常健康的状态应该大致是0.70.8以下,存在一些预留空间。相对的,多核,则在单核的标准上乘以对应核数,则为判断标准。如2核的负载健康标准数据就是0.7 * 2 =1.4

要理解其中原因,就需要理解操作系统的并行假象和分时系统

操作系统的并行假象和分时系统

每核CPU在某一时刻都只能执行一个进程。使用操作系统的人是不会去关注CPU是单核还是多核的,每个人都希望操作系统能同时运行多个程序,比如可以同时看网页、发邮件、聊QQ、听音乐等。

所以操作系统提供的多程序同时运行是『伪并行』。要想实现真正的并行运行多个进程,只能使用多核CPU来实现。

OS营造这种假象的技术是『CPU时间共享(time sharing)』,也称为『分时系统』,即CPU执行一会进程A,然后停下来去执行一会进程B,再停下来执行一会进程A。即,每个进程都只执行一会,然后CPU切换去执行其它进程,每一段执行和切换的时间很短(每秒能执行很多个进程),使得用户以为进程根本未停过,从而形成了假象。

这种不断切换进程的机制,其关键技术就是CPU从一个进程切换到另一个进程,这是通过『上下文切换(context switch)』实现的。上下文切换可以直接理解为进程的切换,之所以使用『上下文』这个术语,是因为CPU要从进程A切换到进程B时,必然要保存进程A的执行环境,比如进入切换时进程A执行到了哪个地方,以便下次切换回进程A的执行环境,比如进入切换时进程A执行到了哪个地方,以便下次切换回进程A的时候能够从这里恢复继续执行,此外,既然要切换到进程B,必要还要恢复之前已保存好的进程B的执行环境,才能知道从哪里开始继续执行进程B。而在计算机世界中,『环境』和『上下文』通常是可以互换的概念,所以CPU的上下文切换是两个前后进程执行环境的切换。

每个进程执行一会就会切换到另一个进程,这个执行的时间就称为时间片。当一个进程耗尽时间片后,将切换到其它进程,那么时间片长好还是短好呢?时间片分配过短,上下文切换就泰国频繁,而上下文切换是有开销的,时间片过长,则每个进程需要等待运行的时间就越长,意味着交互性越差。一个比较常见的时间片长度是100ms,但是现在的Linux(从Linux 2.6.3开始)的时间片是动态计算的,并非完全固定的值。

再考虑另外一个问题,既然要不断的切换进程,操作系统如何选择下一个要执行的进程?

选择下一个要执行的进程,是通过操作系统的进程调度程序,也称为调度器或调度类来决定的,调度器根据一些调度算法策略决定哪个进程将幸运的被选中作为下一个要执行的进程。

进程调度算法策略的两个关键指标正是响应时间周转时间响应时间体现的是交互性和公平性,响应时间越短,表示交互时能更快得到响应,比如当敲下键盘时,用户肯定不希望还要等一段时间才显示字符。周转时间体现的是何时完成任务的问题,周转时间越短,表示从启动开始到执行结束所花的时间更短,也就是更快完成任务。

另外,虽然在分时系统下,通过为每个进程分配固定的时间片能保证每个进程都有机会执行,但总会有一些进程是比较重要的,他们的优先级比较高,他们可以从当前正在执行的进程处抢占CPU,这称为『抢占式多任务处理』。当然,这里的抢占并不是真的无条件抢到CPU,CPU给谁是由操作系统的调度策略决定的,抢占只是表明某进程比较重要,应当优待,比如让该进程尽快执行或让它多执行一会。

Tips: 上面的内容只是为了表达,单核CPU在某一时刻,只能执行一个特定的任务,不存在真正意义上的并行。方便更好的理解CPU负载和核心数的关系。

实际上,Linux系统CPU调度的基本单位是:线程。也就是CPU时间片是分配给线程的,这又涉及到线程调度和切换,与进程的关系,以及多核CPU与多线程的并行问题。而每一个系统,还会有些区别,具体有兴趣的,推荐去看《深入理解Linux内核》

%Cpu(s) 信息解读

Top命令中,CPU的使用情况,可以根据此详细信息看到,默认打开时,是所有CPU的整体平均状态,在TOP命令中,按1可以展示所有CPU的各自的使用情况:

如上图所示,则是4核CPU,每个CPU的使用情况。再按一次1,则隐藏,只展示整体平均值。

在这些信息中,分别有如下信息:

  • us:运行没有修改过优先级的用户进程的CPU时间百分比
  • sy:运行内核进程的CPU时间百分比
  • ni:运行修改过优先级的用户进程的CPU时间百分比
  • id:运行Idle进程的CPU时间百分比
  • wa:等待IO完成的CPU时间百分比
  • hi:硬中断所花费的CPU时间百分比
  • si:软中断所花费的CPU时间百分比
  • st:虚拟机管理程序从此虚拟机中窃取的CPU时间百分比

Tips:CPU既然通电了,它就得运行,那么在它没有任务需要执行的时候,就会执行系统提供的Idle空闲进程,Idle进程的工作非常的轻松,就是累积CPU空闲时间,CPU工作在这种状态下,显然以最低能耗(最小频率)的方式在运行,也就是CPU空闲下来,进行休息的地方。

ok,那么上面出现的,用户进程,内核进程,硬中断,软中断等分别表示什么意思,有什么区别,下面我们一个个进行详细说明:

内核态与用户态 (us,sy,ni数据的意义)

进程可分为两种类型:

  • 内核进程:操作系统自身运行的进程,也称为操作系统进程。
  • 用户进程:不是操作系统自身的进程,而是要实现某些功能,用户自己启动的程序产生的进程。

操作系统自身也是一个程序,它启动之后也会有很多内核进程在后台工作,而且这些内核进程都非常重要,是操作系统正常运行并提供服务的必要进程,比如负责CPU调度的进程,负责内存管理的进程等。

而操作系统要提供程序的运行平台,还要管理各类软硬件资源,那么操作系统必然要以一种最高权限的方式去运行,其它用户进程都必须不能具备这个最高权限。

此外,操作系统必须要在有任何需要的时候掌握CPU的控制权,因为进程是通过CPU去执行的,操作系统掌握了CPU的控制权,就代表操作系统进程开始执行。例如,在任何需要进行进程调度的时候,必须能够立即回到操作系统,让负责进程调度的进程开始根据调度算法去调度下一个进程。

此外,操作系统必须要在任何有需要的时候掌握CPU的控制权,因为进程是通过CPU去执行的,操作系统掌握了CPU的控制权,就代表操作系统进程开始执行。例如,在任何需要进行进程调度的时候,必须能够立即回到操作系统,让负责进程调度的进程开始根据调度算法去调度下一个进程。

总而言之,就是要限制用户进程:

  • 操作系统要具备最高掌控权限,其它用户进程都必须不具备这些权限。
  • 操作系统必须能够在任何有需要的时候暂停某个进程并切换到操作系统内核进程,即拿到CPU的控制权。

要让操作系统具备最高权限,并让用户进程不具备最高权限,CPU提供了两种运行模式:内核模式用户模式

Tips:需注意,内核模式和用户模式这两种进程状态是CPU提供的控制,而不是操作系统提供的。在CPU中一个称为PSW(program status word,程序状态字)的寄存器中保存了和进程有关的一些控制位,例如内核模式和用户模式的进程状态。

这两种模式描述了进程的工作状态,是工作在内核模式下还是工作在用户模式下。在内核模式下,表示具备了最高权限,操作系统自身进程都是工作在内核模式下。在用户模式下,执行的代码将受到一些限制,用户进程都是工作在用户模式下,该模式下的进程不能执行一些关键性的操作,比如用户进程必须不能让他自己也变成内核态进程工作在内核模式下,这样的话,权限的限制就没有意义了。

工作在两种状态下的进程也称为内核态进程用户态进程。通常,为了描述问题时区分内核模式和用户模式的进程,也会把这两种模式称为用户空间和内核空间。

所以,CPU信息中,us则表示用户态进程占用的cpu时间百分比,sy则表示内核态进程占用的cpu时间百分比。 而ni则是修改过优先级的用户态进程占用的cpu时间百分比,这在上面讲过,可以通过设置进程的优先级,来抢占更多的CPU时间。

中断 (hi,si)

上面说到,操作系统需要在任何有需要的时候,暂停用户进程,切换到操作系统内核进程,即拿到CPU控制权,那么要想在任何时候回到操作系统,这就相当于改变了CPU到正常执行流程,所以就需要进行:中断,通过中断,回到操作系统,从而讲CPU控制权交给操作系统。

中断的字面意思就是打断正常执行的流程,但是它表示的是打断流程而不是终止流程。 中断时操作系统中非常重要的机制,正如上面所描述的: 中断用户保证CPU控制权交给操作系统,从而让操作系统可以执行某些操作。

中断分为硬件中断(hi)软件中断(si)

  • 硬件中断:任何硬件,都有自己的中断请求,都可以在需要的时候通过总线向CPU发送硬件中断通知。 比如时钟中断,当进程执行耗光时间片时将产生一个时钟中断,使得能够立即进入操作系统并调度下一个要执行的进程,时钟中断时操作系统具有安全感的保证,只要时钟开始运行后,就意味着操作系统最终总能够获取到CPU控制权。再比如硬盘的IO中断,当硬盘读取所请求的数据完成后,就会发送硬盘IO中断,CPU接到该中断后就会切换到操作系统,让操作系统去处理这个中断事件。
  • 软中断:由软件发送的中断,比如请求一个系统调用(system call)

无论是软中断,还是硬中断,最终的目的都是为了回到操作系统,将CPU交给操作系统。那么中断时如何回到操作系统的呢?欢聚话说,中断时是如何进入内核态的呢?内核态又如何回到用户态呢?

其实,要进入内核态,只需要执行特殊的指令即可,一般称之为trap指令,当执行trap指令后,就会进入内核态,回到操作系统。当操作系统执行完相关操作后,就要回到用户态,要回到用户态也只需执行特殊的指令即可,一般称之为return-from-trap指令。

中断既然是打断CPU的执行流程,那么可能需要重新回到中断点继续正常的执行流程。所以,在发生中断时,需要保存好中断点以及相关的一些状态,以便能够在处理完中断后恢复执行流程继续向下执行。

所以,中断就像是突发事件,处理完后如果恢复到断点处,那么对整个流程来说,中断就像是从未发生过的事一样,但却实实在在的被处理了。但是中断后并不一定会恢复到断点处,因为中断处理程序可能会在恢复断点前直接退出这个执行流程,比如有些硬件中断表示一些异常现象,比如0异常,这些异常可能会导致终止进程。

Steal Time(st)

st的全称是Steal Time,是当hypervisor服务另一个虚拟处理器的时候,虚拟CPU等待实际CPU的时间的百分比。什么意思呢?

比如,一个宿主机有2核CPU,然后虚拟出三个虚拟机,每个虚拟机都分配了1核CPU,那么因为实际CPU只有2核,当都被虚拟机A,B占用后,第三台虚拟机C要执行程序,则要向宿主机进行竞争和等待CPU分配时间片。

所以,st值比较高的话,可能意味着你的云服务器供应商在服务器上过量的出售虚拟机。低st值则意味着你程序在机器上运行良好,并不会经常为了CPU时间与其它虚拟机激烈竞争。这也反应你了你的云服务器供应商没有过量的出售虚拟机。

理解iowait

iowait 表示在一个采样周期内有百分之几的时间属于以下情况:CPU空闲、并且有仍未完成的I/O请求通俗理解就是等待IO设备完成其工作时,CPU的空闲比例。但其实在某些场景下,iowait高并不等于说有异常,需要酌情分析

因为CPU是否繁忙,I/O的并发度等都有关系,需要根据实际情况,实际分析,这个指标升高,只能表达字面的意思,cpu比较空闲,IO有事情在做。

一般情况下,其无法直接得出I/O有瓶颈问题。需要配合iostat等IO查询命令,实际分析。

结束

ok,到此,Linux中,Cpu状态的信息的含义与理解都说完了,通过这些信息,大致就能判断CPU的当前状态。可以更好的方便我们进行服务器的运维,业务的运维等。

有任何疑问,欢迎留言