当前位置: 首页 > 科技观察

再说说top命令中的CPU使用率

时间:2023-03-14 08:29:03 科技观察

通常我们使用top命令来查看系统的性能。在top命令中,我们可以看到很多不同类型的CPU使用率,如下图红框所示:接下来我们来介绍一下这些CPU使用率的含义:us:用户时间,表示用户所花费的时间CPU执行用户进程,包括nicetime。通常希望用户空间CPU越高越好。sy:系统时间,表示CPU在内核中运行的时间,包括IRQ和softirq。较高的系统CPU使用率表明系统的某些部分存在瓶颈。通常值越低越好。ni:nicetime,优先级用户进程在执行过程中占用的CPU利用率百分比。id:空闲时间,表示系统处于空闲状态,等待进程运行。wa:waitingtime,表示CPU等待IO操作完成的时间。系统不应该花很多时间等待IO操作,否则就说明IO出现了瓶颈。hi:hardIRQtime,表示系统处理硬中断所花费的时间。si:softIRQtime,表示系统处理软中断所花费的时间。st:stealtime,是被迫等待(involuntarywait)虚拟CPU时间,此时Hypervisor正在为另一个虚拟处理器服务。当然,单凭上面的解释是很难理解它们的意思的。因此本文主要从源码的角度分析它们代表什么。时钟中断首先我们要知道CPU使用率统计是在哪里进行的。在分析之前,我们先来了解一下时钟中断:时钟中断:是一种硬中断,由时间硬件(systemtimer,一种可编程硬件)产生。当CPU接收到时钟中断信号后,会在处理完当前指令后调用时钟中断处理程序来更新系统时间,执行周期性任务等。可以发现统计CPU使用率都是在时钟中断处理程序中完成的。通过cpu_usage_stat结构记录每个CPU的使用情况,我们看一下它的定义:structcpu_usage_stat{cputime64_tuser;cputime64_tnice;cputime64_tsystem;cputime64_tsoftirq;cputime64_tirq;cputime64_tidle;cputime64_tiowait;cputime64_tsteal;cputime64_tnice;从结构体tguest;的定义可以看出它的每个字段都对应于top命令的CPU使用类型。内核在初始化的时候,会为每个CPU创建一个cpu_usage_stat结构体,用来统计CPU的使用情况。OK,现在我们来分析一下内核是如何统计CPU使用率的。每次执行时钟中断处理程序时,都会调用account_process_tick函数进行CPU占用率统计。下面分析account_process_tick函数的实现://说明:user_tick变量标识当前是否正在执行用户应用if(user_tick){//1。如果CPU正在执行用户程序,则调用account_user_time统计account_user_time(p,cputime_one_jiffy,one_jiffy_scaled);}elseif((p!=rq->idle)||(irq_count()!=HARDIRQ_OFFSET)){//2.如果CPU正在执行内核代码,则调用account_system_time进行统计account_system_time(p,HARDIRQ_OFFSET,cputime_one_jiffy,one_jiffy_scaled);}else{//3.否则说明CPU正在执行空闲进程(即处于空闲进程中)idlestate),然后调用account_idle_time进行统计account_idle_time(cputime_one_jiffy);}}account_process_tick函数主要分为3种情况进行统计,如下:如果CPU正在执行用户程序,则调用account_user_time进行统计。如果CPU正在执行内核代码,调用account_system_time进行统计。否则说明CPU正在执行空闲进程(也就是处于空闲状态),则调用account_idle_time进行统计。CPU使用率统计下面我们分别分析一下这三个统计。1.统计用户程序执行时间统计用户程序执行时间是通过account_user_time函数完成的,我们看一下它的实现:voidaccount_user_time(structtask_struct*p,cputime_tcputime,cputime_tcputime_scaled){//获取CPU的统计结构(每个CPUAcpu_usage_statstructure)structcpu_usage_stat*cpustat=&kstat_this_cpu.cpustat;cputime64_ttmp;...//两种情况下CPU使用率统计//1.如果进程nice值大于0,则计入nice字段//2.如果进程nice值小于等于0,则计入user字段if(TASK_NICE(p)>0)cpustat->nice=cputime64_add(cpustat->nice,tmp);elsecpustat->user=cputime64_add(cpustat->user,tmp);...}account_user_time函数主要分两种情况统计:如果进程的nice值大于0,它会被添加到CPU统计结构的nice字段中。如果进程的nice值小于或等于0,则将其添加到CPU统计结构的用户字段中。这里解释一下进程nice值的作用。nice值越大,进程的优先级越低。因此,nicestatistics主要用于统计低优先级进程的CPU占用率。也说明user和nice统计都属于执行用户程序的CPU时间。2.统计内核代码的执行时间。如果时钟中断发生前CPU处于内核态,也就是说正在执行内核代码。然后会调用account_system_time函数进行统计。account_system_time函数实现如下:voidaccount_system_time(structtask_struct*p,inthardirq_offset,cputime_tcputime,cputime_tcputime_scaled){//获取CPU的统计结构(每个CPU一个cpu_usage_stat结构)structcpu_usage_stat*cpustat=&kstat_this_cpu.cpustat;cputime64_ttmp;...//统计主要分为3种情况//1.如果当前在硬中断执行上下文中,那么会在irq字段中计数//2。如果当前在软中断执行上下文中,那么会被计入softirq域//3。否则会在系统字段中统计,tmp);elsecpustat->system=cputime64_add(cpustat->system,tmp);...}account_system_time函数主要分为3种情况进行统计:如果当前在硬件中断执行上下文中,则将其添加到CPU统计结构中间的irq字段。如果它当前在softirq执行上下文中,则将其添加到CPU统计结构的softirq字段中。否则添加到CPU统计结构的系统字段。从上面的代码可以看出,irq和softirq的统计信息也被认为是内核代码执行时间。3.空闲进程执行时间统计当系统中没有可运行的进程时,空闲进程就会被执行。也就是说,当系统执行空闲进程时,就意味着系统处于空闲状态。空闲进程的执行时间统计由account_idle_time函数完成,实现如下:/CPU统计两种情况用法//1.如果系统有等待I/O操作完成的进程,会被计入iowait字段//2。否则会计入空闲字段if(atomic_read(&rq->nr_iowait)>0)cpustat->iowait=cputime64_add(cpustat->iowait,cputime64);elsecpustat->idle=cputime64_add(cpustat->idle,cputime64);}account_idle_time函数也分两种情况进行统计:如果系统正在等待I/O操作完成的进程,则添加到CPU统计结构的iowait字段中。否则它被添加到CPU统计结构的空闲字段。从上面的分析可以看出,iowait统计也是一种空闲时间。top命令的CPU占用率通过源码分析,我们知道了top命令中各种CPU占用率的含义。下面介绍一下top命令是如何计算各类CPU占用率的。获取各个CPU的使用信息,可以读取/proc/stat文件,如下:[vagrant@localhost~]$cat/proc/statcpu245101142109792395028000cpu0245101142109792395028000...以上结果显示CPU使用信息,第一个第一个行代表所有CPU的总和,而第二行开始代表每个CPU内核的使用信息。因为我的电脑只有一个核心,所以只有一份数据。下面说说这几个数据的含义,从第一个值开始分别是:user,nice,system,idle,iowait,irq,softirq,steal。因此,top命令的CPU使用率计算公式如下:totalCPUtime=user+nice+system+idle+wait+irq+softirq+steal%us=user/totalCPUtime%ni=nice/totalCPU时间%sy=系统/CPU总时间%id=idel/CPU总时间%wa=wait/CPU总时间%hi=irq/CPU总时间%si=softirq/CPU总时间%st=steal/CPU总时间非常简单。小结本文主要分析top命令中CPU使用率的含义和实现原理。希望本文能帮助大家对top命令有更深入的了解。