162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci.. include:: ../disclaimer-zh_TW.rst
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci:Translator: 胡皓文 Hu Haowen <src.res.211@gmail.com>
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci========
862306a36Sopenharmony_ciCPU 負載
962306a36Sopenharmony_ci========
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ciLinux通過``/proc/stat``和``/proc/uptime``導出各種信息,用戶空間工具
1262306a36Sopenharmony_ci如top(1)使用這些信息計算系統花費在某個特定狀態的平均時間。
1362306a36Sopenharmony_ci例如:
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci    $ iostat
1662306a36Sopenharmony_ci    Linux 2.6.18.3-exp (linmac)     02/20/2007
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci    avg-cpu:  %user   %nice %system %iowait  %steal   %idle
1962306a36Sopenharmony_ci              10.01    0.00    2.92    5.44    0.00   81.63
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_ci    ...
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci這裡系統認爲在默認採樣周期內有10.01%的時間工作在用戶空間,2.92%的時
2462306a36Sopenharmony_ci間用在系統空間,總體上有81.63%的時間是空閒的。
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci大多數情況下``/proc/stat``的信息幾乎真實反映了系統信息,然而,由於內
2762306a36Sopenharmony_ci核採集這些數據的方式/時間的特點,有時這些信息根本不可靠。
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci那麼這些信息是如何被搜集的呢?每當時間中斷觸發時,內核查看此刻運行的
3062306a36Sopenharmony_ci進程類型,並增加與此類型/狀態進程對應的計數器的值。這種方法的問題是
3162306a36Sopenharmony_ci在兩次時間中斷之間系統(進程)能夠在多種狀態之間切換多次,而計數器只
3262306a36Sopenharmony_ci增加最後一種狀態下的計數。
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci舉例
3562306a36Sopenharmony_ci---
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci假設系統有一個進程以如下方式周期性地占用cpu::
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci     兩個時鐘中斷之間的時間線
4062306a36Sopenharmony_ci    |-----------------------|
4162306a36Sopenharmony_ci     ^                     ^
4262306a36Sopenharmony_ci     |_ 開始運行           |
4362306a36Sopenharmony_ci                           |_ 開始睡眠
4462306a36Sopenharmony_ci                           (很快會被喚醒)
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci在上面的情況下,根據``/proc/stat``的信息(由於當系統處於空閒狀態時,
4762306a36Sopenharmony_ci時間中斷經常會發生)系統的負載將會是0
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci大家能夠想像內核的這種行爲會發生在許多情況下,這將導致``/proc/stat``
5062306a36Sopenharmony_ci中存在相當古怪的信息::
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	/* gcc -o hog smallhog.c */
5362306a36Sopenharmony_ci	#include <time.h>
5462306a36Sopenharmony_ci	#include <limits.h>
5562306a36Sopenharmony_ci	#include <signal.h>
5662306a36Sopenharmony_ci	#include <sys/time.h>
5762306a36Sopenharmony_ci	#define HIST 10
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_ci	static volatile sig_atomic_t stop;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	static void sighandler (int signr)
6262306a36Sopenharmony_ci	{
6362306a36Sopenharmony_ci	(void) signr;
6462306a36Sopenharmony_ci	stop = 1;
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci	static unsigned long hog (unsigned long niters)
6762306a36Sopenharmony_ci	{
6862306a36Sopenharmony_ci	stop = 0;
6962306a36Sopenharmony_ci	while (!stop && --niters);
7062306a36Sopenharmony_ci	return niters;
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci	int main (void)
7362306a36Sopenharmony_ci	{
7462306a36Sopenharmony_ci	int i;
7562306a36Sopenharmony_ci	struct itimerval it = { .it_interval = { .tv_sec = 0, .tv_usec = 1 },
7662306a36Sopenharmony_ci				.it_value = { .tv_sec = 0, .tv_usec = 1 } };
7762306a36Sopenharmony_ci	sigset_t set;
7862306a36Sopenharmony_ci	unsigned long v[HIST];
7962306a36Sopenharmony_ci	double tmp = 0.0;
8062306a36Sopenharmony_ci	unsigned long n;
8162306a36Sopenharmony_ci	signal (SIGALRM, &sighandler);
8262306a36Sopenharmony_ci	setitimer (ITIMER_REAL, &it, NULL);
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	hog (ULONG_MAX);
8562306a36Sopenharmony_ci	for (i = 0; i < HIST; ++i) v[i] = ULONG_MAX - hog (ULONG_MAX);
8662306a36Sopenharmony_ci	for (i = 0; i < HIST; ++i) tmp += v[i];
8762306a36Sopenharmony_ci	tmp /= HIST;
8862306a36Sopenharmony_ci	n = tmp - (tmp / 3.0);
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ci	sigemptyset (&set);
9162306a36Sopenharmony_ci	sigaddset (&set, SIGALRM);
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_ci	for (;;) {
9462306a36Sopenharmony_ci		hog (n);
9562306a36Sopenharmony_ci		sigwait (&set, &i);
9662306a36Sopenharmony_ci	}
9762306a36Sopenharmony_ci	return 0;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ci參考
10262306a36Sopenharmony_ci---
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci- https://lore.kernel.org/r/loom.20070212T063225-663@post.gmane.org
10562306a36Sopenharmony_ci- Documentation/filesystems/proc.rst (1.8)
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci謝謝
10962306a36Sopenharmony_ci---
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ciCon Kolivas, Pavel Machek
11262306a36Sopenharmony_ci
113