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