18c2ecf20Sopenharmony_ci========
28c2ecf20Sopenharmony_ciCPU 负载
38c2ecf20Sopenharmony_ci========
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ciLinux通过``/proc/stat``和``/proc/uptime``导出各种信息,用户空间工具
68c2ecf20Sopenharmony_ci如top(1)使用这些信息计算系统花费在某个特定状态的平均时间。
78c2ecf20Sopenharmony_ci例如:
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci    $ iostat
108c2ecf20Sopenharmony_ci    Linux 2.6.18.3-exp (linmac)     02/20/2007
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci    avg-cpu:  %user   %nice %system %iowait  %steal   %idle
138c2ecf20Sopenharmony_ci              10.01    0.00    2.92    5.44    0.00   81.63
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci    ...
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci这里系统认为在默认采样周期內有10.01%的时间工作在用户空间,2.92%的时
188c2ecf20Sopenharmony_ci间用在系统空间,总体上有81.63%的时间是空闲的。
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci大多数情况下``/proc/stat``的信息几乎真实反映了系统信息,然而,由于内
218c2ecf20Sopenharmony_ci核采集这些数据的方式/时间的特点,有时这些信息根本不可靠。
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci那么这些信息是如何被搜集的呢?每当时间中断触发时,内核查看此刻运行的
248c2ecf20Sopenharmony_ci进程类型,并增加与此类型/状态进程对应的计数器的值。这种方法的问题是
258c2ecf20Sopenharmony_ci在两次时间中断之间系统(进程)能够在多种状态之间切换多次,而计数器只
268c2ecf20Sopenharmony_ci增加最后一种状态下的计数。
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci举例
298c2ecf20Sopenharmony_ci---
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci假设系统有一个进程以如下方式周期性地占用cpu::
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci     两个时钟中断之间的时间线
348c2ecf20Sopenharmony_ci    |-----------------------|
358c2ecf20Sopenharmony_ci     ^                     ^
368c2ecf20Sopenharmony_ci     |_ 开始运行           |
378c2ecf20Sopenharmony_ci                           |_ 开始睡眠
388c2ecf20Sopenharmony_ci                           (很快会被唤醒)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci在上面的情况下,根据``/proc/stat``的信息(由于当系统处于空闲状态时,
418c2ecf20Sopenharmony_ci时间中断经常会发生)系统的负载将会是0
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci大家能够想象内核的这种行为会发生在许多情况下,这将导致``/proc/stat``
448c2ecf20Sopenharmony_ci中存在相当古怪的信息::
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	/* gcc -o hog smallhog.c */
478c2ecf20Sopenharmony_ci	#include <time.h>
488c2ecf20Sopenharmony_ci	#include <limits.h>
498c2ecf20Sopenharmony_ci	#include <signal.h>
508c2ecf20Sopenharmony_ci	#include <sys/time.h>
518c2ecf20Sopenharmony_ci	#define HIST 10
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	static volatile sig_atomic_t stop;
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci	static void sighandler (int signr)
568c2ecf20Sopenharmony_ci	{
578c2ecf20Sopenharmony_ci	(void) signr;
588c2ecf20Sopenharmony_ci	stop = 1;
598c2ecf20Sopenharmony_ci	}
608c2ecf20Sopenharmony_ci	static unsigned long hog (unsigned long niters)
618c2ecf20Sopenharmony_ci	{
628c2ecf20Sopenharmony_ci	stop = 0;
638c2ecf20Sopenharmony_ci	while (!stop && --niters);
648c2ecf20Sopenharmony_ci	return niters;
658c2ecf20Sopenharmony_ci	}
668c2ecf20Sopenharmony_ci	int main (void)
678c2ecf20Sopenharmony_ci	{
688c2ecf20Sopenharmony_ci	int i;
698c2ecf20Sopenharmony_ci	struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 },
708c2ecf20Sopenharmony_ci				.it_value = { .tv_sec = 0, .tv_usec = 1 } };
718c2ecf20Sopenharmony_ci	sigset_t set;
728c2ecf20Sopenharmony_ci	unsigned long v[HIST];
738c2ecf20Sopenharmony_ci	double tmp = 0.0;
748c2ecf20Sopenharmony_ci	unsigned long n;
758c2ecf20Sopenharmony_ci	signal (SIGALRM, &sighandler);
768c2ecf20Sopenharmony_ci	setitimer (ITIMER_REAL, &it, NULL);
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	hog (ULONG_MAX);
798c2ecf20Sopenharmony_ci	for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX);
808c2ecf20Sopenharmony_ci	for (i = 0; i < HIST; ++i) tmp += v[i];
818c2ecf20Sopenharmony_ci	tmp /= HIST;
828c2ecf20Sopenharmony_ci	n = tmp - (tmp / 3.0);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci	sigemptyset (&set);
858c2ecf20Sopenharmony_ci	sigaddset (&set, SIGALRM);
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci	for (;;) {
888c2ecf20Sopenharmony_ci		hog (n);
898c2ecf20Sopenharmony_ci		sigwait (&set, &i);
908c2ecf20Sopenharmony_ci	}
918c2ecf20Sopenharmony_ci	return 0;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci参考
968c2ecf20Sopenharmony_ci---
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci- http://lkml.org/lkml/2007/2/12/6
998c2ecf20Sopenharmony_ci- Documentation/filesystems/proc.rst (1.8)
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci谢谢
1038c2ecf20Sopenharmony_ci---
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ciCon Kolivas, Pavel Machek
106