Date

原文Linux System and Performance Monitoring,作者Darren Hoch。

3.0 CPU简介

CPU的利用率很大程度取决于运行什么类型的任务。内核调度器服务于两种任务:线程(单或多)和中断。调度器赋予不同任务以不同的优先级,下面是各个任务的优先级排序:

  • 中断——设备通知内核完成了某个操作。比如网卡发送了一个网络包或者某个硬件驱动产生了一个IO请求。
  • 内核进程——所有的内核进程以此优先级运行。
  • 用户进程——即通常所说的用户态。所有的软件应用以用户态运行。在内核调度机制中,用户态优先级最低。

为了便于理解内核如何管理和调度这些任务,下面将介绍一些重点概念:上下文切换、运行队列及利用率。

3.1 上下文切换

大部分现代处理器只能同时运行一个单线程进程或者一个线程。N路超线程或N核处理器则可以同时运行N个线程。其实Linux内核把多核处理器中的每一个核看成一个独立的处理器,例如一个单处理器双核的系统在Linux内核看来就是一个双处理器的系统。

一个标准的Linux内核支持“同时”运行50-50000个线程,如果只有一个CPU,内核必须公平地调度这些线程。每一个线程会被分配一个CPU时间片,一旦线程用完了该时间片或者被更高优先级的任务(比如硬件中断)抢占,线程就会被放回运行队列中,而更高优先级的任务将占用CPU。这种线程之间的切换被称作为上下文切换。

上下文切换时,内核需要消耗一定的资源用于将线程从CPU寄存器移到运行队列。因此,一个系统上下文切换的次数越多,内核用以完成调度工作的额外消耗也就越多。

3.2 运行队列

每一个CPU都维护了一个可运行状态线程的队列。理想状况是调度器一直连续不间断地在执行线程。线程一般要么是在sleep状态(被阻塞或者等待IO完成),要么在可运行状态。在CPU被过度使用时,内核调度器就可能不能立刻执行系统命令,而可运行的线程就可能会充满运行队列。运行队列越大,线程等待执行的时间就可能越长。

一个熟为人知的用于描述运行队列状态的词叫做“负载”。系统的负载的值是正在执行的线程数和等待执行线程数之和。假设,一个双核系统中正有两个线程在执行,还有4个线程在运行队列中等待执行,那么这个系统当前的负载值就是6。Top命令可以统计1/5/15分钟的系统负载均值(即load average)。

3.3 CPU利用率

CPU利用率,即CPU被使用的百分比。CPU的应用情况是衡量一个系统的重要指标。大部分性能监控工具会将CPU的使用分成如下几类:

  • User Time——CPU用于执行用户态线程的时间百分比
  • System Time——CPU用于执行内核线程和中断的时间百分比
  • Wait IO——因为所有线程都在等待IO而CPU处于空闲状态的时间百分比
  • Idle——CPU完全处于空闲状态的时间百分比

译注:Wait IO和Idle的相同点是线程运行队列为空,不同点是Wait IO是线程等待队列非空而Idle是线程等待队列也为空。