监控项 | 说明 | 监控值 |
Load_one | One minute load average 每分钟的系统平均负载 | load_one=0.0 |
Load_five | Five minute load average 每5分钟的系统平均负载 | load_five=0.0 |
Load_fifteen | Fifteen minute load average 每15分钟的系统平均负载 | load_fifteen=0.0 |
mem_total | Total amount of memory displayed in KBs 物理内存总量(KBs显示) | mem_total=2075288.0 |
mem_cached | Amount of cached memory 缓存内存大小 | mem_cached=470732.0 |
mem_free | Amount of available memory 空闲内存大小 | mem_free=1128860.0 |
mem_buffers | Amount of buffered memory 内核缓存的内存总量 | mem_buffers=353264.0 |
swap_total | Total amount of swap space displayed in KBs 交换分区总量(KBs显示) | swap_total=8289532.0 |
swap_free | Amount of available swap memory 空闲交换分区大小 | swap_free=8289532.0 |
mem_shared | Amount of shared memory 共享内存大小 | mem_shared=0.0 |
proc_run | Total number of running processes 运行的进程总数 | proc_run=0.0 |
proc_total | Total number of processes 进程总数 | proc_total=65.0 |
cpu_idle | Percentage of time that the CPU or CPUs were idle and the system did not have an outstanding disk I/O request 空闲CPU百分比 | cpu_idle=99.6 |
cpu_aidle | Percent of time since boot idle CPU 启动的空闲CPU百分比 | cpu_aidle=99.8 |
cpu_user | Percentage of CPU utilization that occurred while executing at the user level 用户空间占用CPU百分比 | cpu_user=0.2 |
cpu_nice | Percentage of CPU utilization that occurred while executing at the user level with nice priority 用户进程空间内改变过优先级的进程占用CPU百分比 | cpu_nice=0.0 |
cpu_system | Percentage of CPU utilization that occurred while executing at the system level 内核空间占用CPU百分比 | cpu_system=0.1 |
cpu_num | Total number of CPUs CPU线程总数 | cpu_num=2.0 |
cpu_speed | CPU Speed in terms of MHz CPU速度(MHz) | cpu_speed=2993.0 |
cpu_wio | Percentage of time that the CPU or CPUs were idle during which the system had an outstanding disk I/O request Cpu空闲时的最大I/O请求 | cpu_wio=0.2 |
part_max_used | Maximum percent used for all partitions | part_max_used=21.2 |
disk_total | Total available disk space 磁盘总大小 | disk_total=133.991 |
disk_free | Total free disk space 剩余磁盘空间 | disk_free=124.707 |
boottime | The last time that the system was started 系统启动时间 | boottime=1285905983.0 |
pkts_in | Packets in per second 每秒进来的包 | pkts_in=10.5 |
pkts_out | Packets out per second 每秒出去的包 | pkts_out=2.85 |
bytes_in | Number of bytes in per second 每秒进来字节数 | bytes_in=769.35 |
bytes_out | Number of bytes out per second 每秒出去字节数 | bytes_out=3674.02 |
machine_type | System architecture 系统版本(X86或64) | machine_type=x86 |
os_name | 系统名字 | os_name=Linux |
os_release | 系统版本 | os_release=2.6.18-164.el5PAE |
gexec | gexec available | gexec=OFF |
disk_free_rootfs | Disk space available on | WARN: ‘ disk_free_rootfs |
获取内核上报的时间戳是通过进程轮询的方式,但是发现该进程在实际运行中CPU占用率很高,其中就是一个死循环在读取设备文件,本以为是由于读系统调用太频繁的原因。
于是又写一个测试程序,其中仅仅是个空循环。结果发现该程序的CPU占用率居然在90%多!
针对这个问题我有2个疑问,对这些疑问的理解也记录在此,与大家分享。
1 linux系统是时间片调度算法,微观上所有可运行进程都是串行,不管进程中作何操作,该进程的时间片一到就切换到下一进程,那为什么一个空循环进程CPU占用率还这么高。
要彻底搞明白这个问题,需要弄清楚2个问题
(1)linux进程的几种状态以及其切换关系。
(2)CPU占用率如何计算出来的。
linux进程的几种状态以及其切换关系在《深入学习linux内核》中有详细介绍,这里简单说下。
进程是一个动态的实体,所以他是有生命的。从创建到消亡,是一个进程的整个生命周期。在这个周期中,进程可能会经历各种不同的状态。一般来说,所有进程都要经历以下的3个状态:
就绪态。指进程已经获得所有所需的其他资源,正在申请处理处理器资源,准备开始执行。这种情况下,称进程处于就绪态。
阻塞态。指进程因为需要等待所需资源而放弃处理器(如系统调用阻塞或者sleep),或者进程本不拥有处理器,且其他资源也没有满足,从而即使得到处理器也不能开始运行。这种情况下,进程处于阻塞态。阻塞状态也称休眠状态或者等待状态。
运行态。进程得到了处理器,并不需要等待其他任何资源,正在执行的状态,称之为运行态。只有在运行态时,进程才可以使用所申请到的资源。在所有进程中同一时刻仅有一个进程处于运行态。
在Linux系统中,将各种状态进行了重新组织,由此得到了Linux进程的几个状态:
RUNNING:正在运行或者在就绪队列中等待运行的进程。也就是上面提到的运行态和就绪态进程的综合。一个进程处于RUNNING状态,并不代表他一定在被执行。由于在多任务系统中,各个就绪进程需要并发执行,所以在某个特定时刻,这些处于RUNNING状态的进程之中,只有一个能得到处理器,而其他进程必须在一个就绪队列中等待。即使是在多处理器的系统中,Linux也只能同时让一个处理器执行任务。
UNINTERRUPTABLE:不可中断阻塞状态。处于这种状态的进程正在等待队列中,当资源有效时,可由操作系统进行唤醒,否则,将一直处于等待状态。
INTERRUPTABLE:可中断阻塞状态。与不可中断阻塞状态一样,处于这种状态的进程在等待队列中,当资源有效时,可以有操作系统进行唤醒。与不可中断阻塞状态有所区别的是,处于此状态中的进程亦可被其他进程的信号唤醒。
STOPPED:挂起状态。进程被暂停,需要通过其它进程的信号才能被唤醒。导致这种状态的原因有两种。其一是受到相关信号(SIGSTOP,SIGSTP,SIGTTIN或SIGTTOU)的反应。其二是受到父进程ptrace调用的控制,而暂时将处理器交给控制进程。
ZOMBIE:僵尸状态。表示进程结束但尚未消亡的一种状态。此时进程已经结束运行并释放掉大部分资源,但尚未释放进程控制块。
使用PS命令查看进程时可以看到,“S”进程是指处于阻塞状态,“R”进程处于就绪或运行状态。
进一步理解,linux 进行进程调度时是对就绪队列中的进程进行时间片的分配。而阻塞状态和挂起状态的进程都处在阻塞队列中,只有唤醒后才能加入就绪队列中等待内核的调度。
再来看CPU占有率是如何计算出来的。
首先需要明白的是只要设备上电CPU就不会闲着,总会有某个进程占用CPU运行,linux内核启动最终会启动cpu_idle进程,在该进程中会死循环调用schedule函数进行调度,即使就绪队列中没有进程可以调度,也就是说没有进程时RUNNING状态,CPU也会一直在cpu_idle中死循环。而我们常说的CPU被占用其实是指就绪队列中有进程被调度使用CPU,CPU占有率也就是该进程使用CPU的的一个百分比。
搞明白了以上两点,再反过来看我们的问题。为什么空循环进程CPU占用率高呢。
可以想象,空循环进程中虽然没做任何事情,却没有阻塞条件(如sleep),进程一直处于RUNNING状态,也就是说即使该进程时间片到了被切换,该进程还是处于就绪队列,等待下次调度。
linux内核的调度算法是很复杂的,根据UTLK介绍,关键因素在于时间片的分配和优先级的计算,优先级越高的进程时间片分配越长。
这里咱们去繁就简,假设linux内核调度算法仅仅是等时时间片调度,也就是说1s内所有运行进程时间片是相等的,其实就是将1s时间平分给就绪队列中的所有进程。所以问题的关键就是就绪队列中有多少个进程来平分这个时间了。
对我的设备中ps命令查看进程状态,发现只有空循环进程是RUNNING状态的。
但是由于运行top命令时top也是一个RUNNING进程,因此这时的linux内核仅仅对这2个进程进行来回调度,当然空循环进程的CPU占用率高了!
2 既然CPU一直被占用,CPU负载高低如何解释,空循环进程对系统有什么影响。
想明白空循环进程问题后我就对CPU负载高低产生了疑问,既然CPU一直有进程占用,也就是说CPU其实是一直满载的,为什么还有负载高低这一说。
我的理解是这样的,对于CPU来说,它一直是按照固定的频率取指令运行,没有负载高低之说,我们所说的负载高低其实是人感官的说法,比如top查看发现CPU占用率高,系统主要应用进程(如sh)反应慢,我们就说负载高。
打个形象点的比方,CPU可以比喻为家庭机器人,可以进行做饭 洗衣服 扫地,机器人做这些工作的速度是不变的。做饭10分钟完成,但是如果要求它做饭 洗衣服 扫地同时进行,站在机器人的角度来说,没有差别,速度是一样的。但是从我们的角度来看我们的主要应用-做饭,就发现它做饭慢了,我们就认为机器人是不是负载太高啦。
因此空循环对系统的影响也就好理解了,就会导致就绪队列中无意义的进程多了,但一个空循环进程影响不明显。
就绪队列中本来只有2个进程,主应用进程在1s内可以运行0.5s,但是如果有20个进程,则只可以运行0.05s,进程的执行响应效率也就下来了。
这里可以做一个简单的试验,在我的设备系统中启动几十个空循环进程,发现系统控制台反应都慢了,这就验证了以上说法。