linux概念之cpu分析

http://ilinuxkernel.com/?cat=4

Linux CPU占用率原理与精确度分析
1  CPU占用率计算原理
在Linux/Unix 下,CPU 利用率分为用户态、系统态和空闲态,分别表示CPU 处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。
下面是top显示的值
1.1%us,  1.6%sy,  0.0%ni, 97.2%id,  0.0%wa,  0.0%hi,  0.1%si,  0.0%st
      us: User time         用户时间
      sy: System time         系统时间
      ni: Nice time         Nice时间
      id: Idle time         空闲时间
      wa: Waiting time         等待时间
      hi: Hard Irq time     硬中断处理时间
      si: SoftIrq time         软中断处理时间
      st: Steal time         丢失时间
表示CPU 执行用户进程的时间,包括nices时间。通常期望用户空间CPU 越高越好。
表示CPU 在内核运行时间,包括IRQ 和softirq 时间。系统CPU 占用率高,表明系统某部分存在瓶颈。通常值越低越好。
系统调整进程优先级所花费的时间。
系统处于空闲期,等待进程运行。
CPU在等待I/O 操作完成所花费的时间。系统不应该花费大量时间来等待I/O 操作,否则就说明I/O 存在瓶颈。
系统处理硬中断所花费的时间。
系统处理软中断所花费的时间。
被强制等待(involuntary wait)虚拟CPU的时间,此时 hypervisor 在为另一个虚拟处理器服务。

1.2  CPU 占用率计算
Linux CPU 占用率计算,都是根据/proc/stat文件内容计算而来,下面是stat文件内容样例,内核版本不同,会稍有不同,但内容基本一致。
CPU 信息,cpu 为总的信息,cpu0 … cpun 为各个具体CPU 信息      
cpu 661733 468 503925 233055573 548835 14244 15849 0
       上面共有8 个值(单位:ticks),分别为:
       User time , 661733                Nice time , 468
       System time , 503925              Idle time ,233055573
       Waiting time,548835               Hard   Irq time , 14244
       SoftIRQ time,15849                Steal time,0
 
     CPU占用率计算公式如下:     
     CPU 时间=user+system+nice+idle+iowait+irq+softirq+Stl
     %us =(User time + Nice time)/CPU时间*100%
     %sy=(System time + Hard Irq time +SoftIRQ time)/CPU时间*100%
     %id=(Idle time)/CPU 时间*100%
     %ni=(Nice time)/CPU 时间*100%
     %wa=(Waiting time)/CPU时间*100%
     %hi=(Hard Irq time)/CPU 时间*100%
     %si=(SoftIRQ time)/CPU时间*100%
     %st=(Steal time)/CPU时间*100%

2  CPU占用率内核实现
下面以RHEL6 内核源码版本2.6.32-220.el6 x86_64 为例,来介绍内核源码实现。/proc/stat 文件的创建由函数proc_stat_init()实现,在文件 fs/proc/stat.c 中,在内核初始化时调用。/proc/stat 文件相关函数时间均在stat.c 文件中。
3  Linux CPU占用率精确性分析
在使用类似top 命令,观察系统及各进程CPU 占用率时,可以指定刷新时间间隔,以及时刷新和实时观察CPU 占用率。top 命令默认情况下,是每 3 秒刷新一次。也可以通过 top  -d <刷新时间间隔> 来指定刷新频率,如top -d 0.1 或top -d 0.01 等。top 执行时,也可以按“s ”键,修改时间间隔。
我们可以将CPU 占用率刷新间隔设置很低,如0.01 秒。但过低的刷新频率是否能够更准确观察到CPU 占用率?Linux  系统提供的CPU 占用率信息是否足够精确?
根据前面分析,我们已知 Linux 是根据/proc/stat 文件的内容来计算CPU 占用率,也就是精确度和/proc/stat 提供的数据精确度有关。那么
(1)/proc/stat 文件中的内容单位是什么?
(2)多久会刷新/proc/stat 中的数据?
  cpu    926 0 4160 5894903 2028 0 7 0 0
  cpu0     80 0 473 367723 658 0 3 0 0
3.1  /proc/stat中的数据单位精度
/proc/stat 中CPU 数据信息,单位是ticks。内核中有个全局变量jiffies ,来记录系统启动以来,经历的ticks 数量。

[[email protected] boot]# cat /proc/sched_debug|grep ji
  .jiffies                                 : 9645728927
[[email protected] boot]# cat /proc/stat
cpu  216511 1316 58661 534345575 29219 2170 3034 0 0
ticks(滴答)就是系统时钟中断的时间间隔,该值与内核中HZ值有关,即ticks = 1/HZ。HZ值的大小,在内核编译时可配置的。某台机器上是RHEL6.1 内核,配置的HZ值为1000。
[[email protected] boot]# uname -a
Linux ssd 2.6.32-131.0.15.el6.x86_64 #1 SMP Tue May 10 15:42:40 EDT 2011 x86_64 x86_64 x86_64 GNU/Linux
[[email protected] boot]# cat /boot/config-2.6.32-431.el6.x86_64|grep CONFIG_HZ
# CONFIG_HZ_100 is not set
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
CONFIG_HZ_1000=y
CONFIG_HZ=1000
HZ 的值,就是每秒的时钟中断数量。可以观察/proc/interrupts 中时钟中断值变化,来计算HZ的值。当HZ的值为1000时,ticks 的单位即为1/1000秒,即1ms 。
[[email protected] boot]# cat /proc/interrupts |grep LOC
LOC:   30099358   Local timer interrupts
3.2
/proc/stat文件中的值,都是在程序读取时更新,内核并不会主动更新/proc/stat 中的数据。
/proc/stat 中的CPU 信息是通过kernel_stat 各个成员变量的值计算而来。
3.3  CPU利用率精确性分析
通过前面分析,我们可以得出以下结论:
  (1)Linux CPU 占用率是根据/proc/stat 文件中的数据计算而来;
  (2)/proc/stat 中的数据精度为ticks ,即1/HZ秒;
  (3)内核每个ticks 会更新一次CPU 使用信息;
  (4)CPU 占用率的精度为1/HZ秒。
4  Linux CPU占用率是否准确?
有时偶尔会遇到类似问题:在稳定计算压力下,进程CPU 占用率不稳定;或者特性进程CPU 占用率明显不准。即在系统切换次数很高时,Linux 的CPU 利用率计算机制可能不准确。那么Linux 的CPU 利用率计算到底是否准确?若可能不准确,则什么情况下出现这种情况?
4.1  Linux CPU 占用率不准确情形
在前面分析中,Linux 内核是在每次时钟中断时更新CPU 使用情况,即 1/HZ秒更新一次。时钟中断时,只会看到当前正在运行的进程信息。以下图为例,红色箭头表示时钟中断(Timer Interrupt )。
第一次中断时,看到进程A 在运行。但进程 A 运行时间短,进程 B 运行。第二次中断时,进程 C 运行;在第三次中断到来时,再次调度进程 A 执行。第三次此中断时,进程C 运行。
按照Linux 内核CPU 占用率统计方法,在第1 次和第2 次中断期间,内核并没有看到进程B 在运行;于是就漏掉了进程B 使用CPU 的信息。同样道理,在第2 次和第3次中断期间,漏掉了进程B 使用CPU 的情况。这样,就导致了Linux 内核CPU 占用率统计不准确。
发生CPU占用率不准确的原因是:在一个时钟中断周期内,发生了多次进程调度。时钟中断的精度是1/HZ秒。
4.2  top 命令CPU使用率准确吗?
只有在一个时钟中断周期内发生多次进程调度,才会出现CPU 占用率不准的情况。那么top 命令中CPU 使用率是否准确与进程调度频率有关。若HZ的值为250 ,则 ticks 值为4ms ;若 HZ值为1000,则 ticks 值为1ms 。在 HZ为250 时,只要进程的调度间隔大于4ms ,CPU 占用率就准确。HZ为1000时,调度间隔大于1ms ,CPU 占用率计算就准确。进程调度次数少,CPU占用率就准确;调度时间间隔小于时钟中断,就可能不准确。那么进程调度的时机是怎样的?如何观察进程调度次数?
4.2.1  进程调度时机
1.进程状态转换的时刻:进程终止、进程睡眠
进程要调用sleep()或 exit ()等函数进行状态转换,这些函数会主动调用调度程序进行进程调度;
2.当前进程的时间片用完时(current->counter=0 )
由于进程的时间片是由时钟中断来更新的
3.设备驱动程序
当设备驱动程序执行长而重复的任务时,直接调用调度程序。在每次反复循环中,驱动程序都检查need_resched的值,如果必要,则调用调度程序schedule() 主动放弃CPU 。
4.进程从中断、异常及系统调用返回到用户态时
不管是从中断、异常还是系统调用返回,最终都调用ret_from_sys_call (),由这个函数进行调度标志的检测,如果必要,则调用调度程序。那么,为什么从系统调用返回时要调用调度程序呢?这当然是从效率考虑。从系统调用返回意味着要离开内核态而返回到用户态,而状态的转换要花费一定的时间,因此,在返回到用户态前,系统把在内核态该处理的事全部做完。
4.2.2  进程调度次数观察
可以通过vmstat 命令,来观察系统中进程切换次数,cs 域的值就是切换次数。HZ的值,可以通过内核配置文件来确定,若/proc/config.gz 存在,导出这个文件查看即可。
也可以通过查看/proc/sched_debug 文件内容,来观察切换次数(nr_switches)。
[[email protected] proc]# watch -d -n 1 ‘cat /proc/sched_debug |grep nr_switches‘
 
我们系统中的进程调度真的那么频繁吗?大多数情况下,Linux 中的CPU 占用率计算机制是准确的。

时间: 2024-12-28 16:25:34

linux概念之cpu分析的相关文章

Linux下high CPU分析心得【非原创】

非原创,搬运至此以作笔记, 原地址:http://www.cnitblog.com/houcy/archive/2012/11/28/86801.html 1.用top命令查看哪个进程占用CPU高gateway网关进程14094占用CPU高达891%,这个数值是进程内各个线程占用CPU的累加值. PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND     14094 root      15   0  315m 

Linux 线程实现机制分析 Linux 线程实现机制分析 Linux 线程模型的比较:LinuxThreads 和 NPTL

Linux 线程实现机制分析 Linux 线程实现机制分析  Linux 线程模型的比较:LinuxThreads 和 NPTL http://www.ibm.com/developerworks/cn/linux/kernel/l-thread/ 自从多线程编程的概念出现在 Linux 中以来,Linux 多线应用的发展总是与两个问题脱不开干系:兼容性.效率.本文从线程模型入手,通过分析目前 Linux 平台上最流行的 LinuxThreads 线程库的实现及其不足,描述了 Linux 社区是

Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7)【转】

原文地址:Linux内核源码分析--内核启动之(5)Image内核启动(rest_init函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938395.html 前面粗略分析start_kernel函数,此函数中基本上是对内存管理和各子系统的数据结构初始化.在内核初始化函数start_kernel执行到最后,就是调用rest_init函数,这个函数的主要使命就是创建并启动内核线

Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7)【转】

原文地址:Linux内核源码分析--内核启动之(6)Image内核启动(do_basic_setup函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938396.html 在基本分析完内核启动流程的之后,还有一个比较重要的初始化函数没有分析,那就是do_basic_setup.在内核init线程中调用了do_basic_setup,这个函数也做了很多内核和驱动的初始化工作,详解

Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 【转】

原文地址:Linux内核源码分析--内核启动之(3)Image内核启动(C语言部分)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938390.html 在构架相关的汇编代码运行完之后,程序跳入了构架无关的内核C语言代码:init/main.c中的start_kernel函数,在这个函数中Linux内核开始真正进入初始化阶段, 下面我就顺这代码逐个函数的解释,但是这里并不会过于深入

Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】

原文地址:Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7) 作者:tekkamanninja 转自:http://blog.chinaunix.net/uid-25909619-id-4938393.html 在分析start_kernel函数的时候,其中有构架相关的初始化函数setup_arch. 此函数根据构架而异,对于ARM构架的详细分析如下: void __init setup_arch(char **cmdlin

linux下面的性能分析工具简介

iostat 命令详解 iostat用于输出cpu和磁盘I/O相关的统计信息.命令格式: Usage: iostat [ options ] [ <interval> [ <count> ] ] Options are: [ -c ] [ -d ] [ -N ] [ -n ] [ -h ] [ -k | -m ] [ -t ] [ -V ] [ -x ] [ -y ] [ -z ] [ -j { ID | LABEL | PATH | UUID | ... } [ <devi

linux服务器的性能分析与优化(十三)

[教程主题]:1.linux服务器的性能分析与优化 [主要内容] [1]影响Linux服务器性能的因素 操作系统级 Ø CPU 目前大部分CPU在同一时间只能运行一个线程,超线程的处理器可以在同一时间处理多个线程,因此可以利用超线程特性提高系统性能. 在linux系统下只有运行SMP内核才能支持超线程,但是安装的CPu数量越多,从超线程获得的性能提升越少. 另外linux内核会将多核的处理器当做多个单独的CPU来识别,例如,两个4核的CPU会被当成8个单个CPU,从性能角度讲,两个4核的CPU整

1.linux服务器的性能分析与优化

[教程主题]:1.linux服务器的性能分析与优化 [课程录制]: 创E [主要内容] [1]影响Linux服务器性能的因素 操作系统级 CPU 目前大部分CPU在同一时间只能运行一个线程,超线程的处理器可以在同一时间处理多个线程,因此可以利用超线程特性提高系统性能. 在linux系统下只有运行SMP内核才能支持超线程,但是安装的CPu数量越多,从超线程获得的性能提升越少. 另外linux内核会将多核的处理器当做多个单独的CPU来识别,例如,两个4核的CPU会被当成8个单个CPU,从性能角度讲,