詳解Linux中計算特定CPU使用率案例
Linux中計算特定CPU使用率 需求解決方案拓展參考
#需求
在Linux中可以透過top指令查看某一進程所佔用的CPU情況,也可以查看某一個CPU使用率狀況(先top指令,然後按數字「1」鍵即可顯示每一個CPU的使用情況) ,如下圖:
#而我們的需求是:如何得到一個CPU的佔用率呢?
解決方案
1. 背景知識
#在/proc/stat中可以查看每一個CPU的使用情況的,如下圖:
#其中cpu(0/1/2/…)後面的十個數字意義如下:
/proc/stat kernel/system statistics. Varies with architecture. Common entries include: user nice system idle iowait irq softirq steal guest guest_nice cpu 4705 356 584 3699 23 23 0 0 0 0 cpu0 1393280 32966 572056 13343292 6130 0 17875 0 23933 0 The amount of time, measured in units of USER_HZ (1/100ths of a second on most architectures, use sysconf(_SC_CLK_TCK) to obtain the right value), that the system ("cpu" line) or the specific CPU ("cpuN" line) spent in various states: user (1) Time spent in user mode. nice (2) Time spent in user mode with low priority (nice). system (3) Time spent in system mode. idle (4) Time spent in the idle task. This value should be USER_HZ times the second entry in the /proc/uptime pseudo-file. iowait (since Linux 2.5.41) (5) Time waiting for I/O to complete. This value is not reliable, for the following rea‐ sons: 1. The CPU will not wait for I/O to complete; iowait is the time that a task is waiting for I/O to complete. When a CPU goes into idle state for outstanding task I/O, another task will be scheduled on this CPU. 2. On a multi-core CPU, the task waiting for I/O to complete is not running on any CPU, so the iowait of each CPU is difficult to calculate. 3. The value in this field may decrease in cer‐ tain conditions. irq (since Linux 2.6.0-test4) (6) Time servicing interrupts. softirq (since Linux 2.6.0-test4) (7) Time servicing softirqs. steal (since Linux 2.6.11) (8) Stolen time, which is the time spent in other operating systems when running in a virtu‐ alized environment guest (since Linux 2.6.24) (9) Time spent running a virtual CPU for guest operating systems under the control of the Linux kernel. guest_nice (since Linux 2.6.33) (10) Time spent running a niced guest (virtual CPU for guest operating systems under the con‐ trol of the Linux kernel).
2.計算具體CPU使用率
有了上面的背景知識,接下來我們就可以計算出特定CPU的使用情況了。具體計算方式如下:
Total CPU time since boot = user+nice+system+idle+iowait+irq+softirq+steal Total CPU Idle time since boot = idle + iowait Total CPU usage time since boot = Total CPU time since boot - Total CPU Idle time since boot Total CPU percentage = Total CPU usage time since boot/Total CPU time since boot * 100%
有了上面的計算公式,計算某一CPU使用率或是系統總的CPU佔用率也就是不難了。
範例:計算系統整體CPU佔用情況
首先從/proc/stat取得t1時刻系統整體的user、nice、system、idle、iowait、irq、softirq、steal、guest、guest_nice的值,得到此時Total CPU time since boot(記為total1)和Total CPU idle time since boot(記為idle1)。
其次,從/proc/stat中取得t2時刻系統總的Total CPU time since boot(記為total2)和Total CPU idle time since boot(記為idle2)。 (方法同上一步)
最後,計算t2與t1之間系統總的CPU使用情形。也就是:
CPU percentage between t1 and t2 = ((total2-total1)-(idle2-idle1))/(total2-total1)* 100%
其中, ((total2-total1)-(idle2-idle1))其實就是t1與t2時刻之間系統CPU被佔用的時間(總時間 - 空閒時間)。
以下是一段計算時間段內CPU被佔用情況的腳本:
#!/bin/bash # by Paul Colby (http://colby.id.au), no rights reserved ;) PREV_TOTAL=0 PREV_IDLE=0 while true; do # Get the total CPU statistics, discarding the 'cpu ' prefix. CPU=(`sed -n 's/^cpu\s//p' /proc/stat`) IDLE=${CPU[3]} # Just the idle CPU time. # Calculate the total CPU time. TOTAL=0 for VALUE in "${CPU[@]}"; do let "TOTAL=$TOTAL+$VALUE" done # Calculate the CPU usage since we last checked. let "DIFF_IDLE=$IDLE-$PREV_IDLE" let "DIFF_TOTAL=$TOTAL-$PREV_TOTAL" let "DIFF_USAGE=(1000*($DIFF_TOTAL-$DIFF_IDLE)/$DIFF_TOTAL+5)/10" echo -en "\rCPU: $DIFF_USAGE% \b\b" # Remember the total and idle CPU times for the next check. PREV_TOTAL="$TOTAL" PREV_IDLE="$IDLE" # Wait before checking again. sleep 1 done
拓展
在核心中,關於/proc/stat中檔案的實作函數如下:
附注:内核版本3.14.69,文件为 /fs/proc/stat.c #include <linux/cpumask.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/kernel_stat.h> #include <linux/proc_fs.h> #include <linux/sched.h> #include <linux/seq_file.h> #include <linux/slab.h> #include <linux/time.h> #include <linux/irqnr.h> #include <asm/cputime.h> #include <linux/tick.h> #ifndef arch_irq_stat_cpu #define arch_irq_stat_cpu(cpu) 0 #endif #ifndef arch_irq_stat #define arch_irq_stat() 0 #endif #ifdef arch_idle_time static cputime64_t get_idle_time(int cpu) { cputime64_t idle; idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; if (cpu_online(cpu) && !nr_iowait_cpu(cpu)) idle += arch_idle_time(cpu); return idle; } static cputime64_t get_iowait_time(int cpu) { cputime64_t iowait; iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; if (cpu_online(cpu) && nr_iowait_cpu(cpu)) iowait += arch_idle_time(cpu); return iowait; } #else static u64 get_idle_time(int cpu) { u64 idle, idle_time = -1ULL; if (cpu_online(cpu)) idle_time = get_cpu_idle_time_us(cpu, NULL); if (idle_time == -1ULL) /* !NO_HZ or cpu offline so we can rely on cpustat.idle */ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE]; else idle = usecs_to_cputime64(idle_time); return idle; } static u64 get_iowait_time(int cpu) { u64 iowait, iowait_time = -1ULL; if (cpu_online(cpu)) iowait_time = get_cpu_iowait_time_us(cpu, NULL); if (iowait_time == -1ULL) /* !NO_HZ or cpu offline so we can rely on cpustat.iowait */ iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT]; else iowait = usecs_to_cputime64(iowait_time); return iowait; } #endif static int show_stat(struct seq_file *p, void *v) { int i, j; unsigned long jif; u64 user, nice, system, idle, iowait, irq, softirq, steal; u64 guest, guest_nice; u64 sum = 0; u64 sum_softirq = 0; unsigned int per_softirq_sums[NR_SOFTIRQS] = {0}; struct timespec boottime; user = nice = system = idle = iowait = irq = softirq = steal = 0; guest = guest_nice = 0; getboottime(&boottime); jif = boottime.tv_sec; for_each_possible_cpu(i) { user += kcpustat_cpu(i).cpustat[CPUTIME_USER]; nice += kcpustat_cpu(i).cpustat[CPUTIME_NICE]; system += kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM]; idle += get_idle_time(i); iowait += get_iowait_time(i); irq += kcpustat_cpu(i).cpustat[CPUTIME_IRQ]; softirq += kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ]; steal += kcpustat_cpu(i).cpustat[CPUTIME_STEAL]; guest += kcpustat_cpu(i).cpustat[CPUTIME_GUEST]; guest_nice += kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE]; sum += kstat_cpu_irqs_sum(i); sum += arch_irq_stat_cpu(i); for (j = 0; j < NR_SOFTIRQS; j++) { unsigned int softirq_stat = kstat_softirqs_cpu(j, i); per_softirq_sums[j] += softirq_stat; sum_softirq += softirq_stat; } } sum += arch_irq_stat(); seq_puts(p, "cpu "); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice)); seq_putc(p, '\n'); for_each_online_cpu(i) { /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ user = kcpustat_cpu(i).cpustat[CPUTIME_USER]; nice = kcpustat_cpu(i).cpustat[CPUTIME_NICE]; system = kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM]; idle = get_idle_time(i); iowait = get_iowait_time(i); irq = kcpustat_cpu(i).cpustat[CPUTIME_IRQ]; softirq = kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ]; steal = kcpustat_cpu(i).cpustat[CPUTIME_STEAL]; guest = kcpustat_cpu(i).cpustat[CPUTIME_GUEST]; guest_nice = kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE]; seq_printf(p, "cpu%d", i); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(user)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(nice)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(system)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(idle)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(iowait)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(irq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(softirq)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(steal)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest)); seq_put_decimal_ull(p, ' ', cputime64_to_clock_t(guest_nice)); seq_putc(p, '\n'); } seq_printf(p, "intr %llu", (unsigned long long)sum); /* sum again ? it could be updated? */ for_each_irq_nr(j) seq_put_decimal_ull(p, ' ', kstat_irqs_usr(j)); seq_printf(p, "\nctxt %llu\n" "btime %lu\n" "processes %lu\n" "procs_running %lu\n" "procs_blocked %lu\n", nr_context_switches(), (unsigned long)jif, total_forks, nr_running(), nr_iowait()); seq_printf(p, "softirq %llu", (unsigned long long)sum_softirq); for (i = 0; i < NR_SOFTIRQS; i++) seq_put_decimal_ull(p, ' ', per_softirq_sums[i]); seq_putc(p, '\n'); return 0; } static int stat_open(struct inode *inode, struct file *file) { size_t size = 1024 + 128 * num_possible_cpus(); char *buf; struct seq_file *m; int res; /* minimum size to display an interrupt count : 2 bytes */ size += 2 * nr_irqs; /* don't ask for more than the kmalloc() max size */ if (size > KMALLOC_MAX_SIZE) size = KMALLOC_MAX_SIZE; buf = kmalloc(size, GFP_KERNEL); if (!buf) return -ENOMEM; res = single_open(file, show_stat, NULL); if (!res) { m = file->private_data; m->buf = buf; m->size = ksize(buf); } else kfree(buf); return res; } static const struct file_operations proc_stat_operations = { .open = stat_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, }; static int __init proc_stat_init(void) { proc_create("stat", 0, NULL, &proc_stat_operations); return 0; } fs_initcall(proc_stat_init);
參考
http://man7.org/linux/man-pages/man5/proc.5.html
//m.sbmmt.com/link/f45cc474bff52cb1b2268a2f94a2abcf
#//m.sbmmt.com/link/73d02e4344f71a0b0d51a925246990e7
以上是詳解Linux中計算特定CPU使用率案例的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undress AI Tool
免費脫衣圖片

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

在Linux上安裝軟件主要有三種方法:1.使用包管理器,如apt、dnf或pacman,通過更新源後執行install命令安裝,例如sudoaptinstallcurl;2.對於.deb或.rpm文件,分別使用dpkg或rpm命令安裝,並在需要時修復依賴;3.使用snap或flatpak跨平台安裝應用,如sudosnapinstall軟件名,適用於追求版本更新的用戶,推薦優先使用系統自帶包管理器以獲得更好的兼容性和性能。

cronisusedforpreciseschedulingonalways-onsystems,whileanacronensuresperiodictasksrunonsystemsthataren'tcontinuouslypowered,suchaslaptops;1.Usecronforexacttiming(e.g.,3AMdaily)viacrontab-ewithsyntaxMINHOURDOMMONDOWCOMMAND;2.Useanacronfordaily,weekly,o

ChoosePop!_OS,Ubuntu,NobaraLinux,orArchLinuxforoptimalgamingperformancewithminimaloverhead.2.InstallofficialNVIDIAproprietarydriversforNVIDIAGPUs,ensureup-to-dateMesaandkernelversionsforAMDandIntelGPUs.3.EnabletheperformanceCPUgovernor,usealow-latenc

Linux適合老舊硬件、安全性高、可定制,但軟件兼容性弱;Windows軟件豐富、易用,但資源佔用高。 1.性能上,Linux輕量高效,適合舊設備;Windows對硬件要求高。 2.軟件上,Windows兼容性更廣,尤其專業工具和遊戲;Linux需借助工具運行部分軟件。 3.安全上,Linux權限管理更嚴格,更新便捷;Windows雖有防護但仍易受攻擊。 4.使用難度上,Linux學習曲線陡峭;Windows操作直觀。根據需求選擇:重性能與安全選Linux,重兼容與易用選Windows。

timessynchronizationiscroucialforsystemriabilitile andsecurityBecurityBecurityBecurityTimecauseslogConfusion,SecurityFailures,不正確的SCHEDULEDTASKS,and distributedSystementerors; 1.CheckntpStatusptatususistimeDimeDimeDatectlstatectlstatustatustoconFirmSynChronChronChronChronizationServiciative and servicivity; 2

RAIDimprovesstorageperformanceandreliabilityonLinuxserversthroughvariousconfigurations;RAID0offersspeedbutnoredundancy;RAID1providesmirroringforcriticaldatawith50�pacityloss;RAID5supportssingle-drivefailuretoleranceusingparityandrequiresatleastthre

要管理Linux服務的開機啟動,使用systemctl命令即可。 1.檢查服務狀態:systemctlstatus可查看服務是否運行、啟用或禁用。 2.啟用服務開機啟動:sudosystemctlenable,如sudosystemctlenablenginx,若同時啟動則用sudosystemctlenable--nownginx。 3.禁用服務開機啟動:sudosystemctldisable,如sudosystemctldisablecups,若同時停止則用sudosystemctldisabl

InstallPythonandessentialtoolsusingyourdistribution’spackagemanager,ensuringpython3-venvandpython3-devareincludedforenvironmentisolationandCextensions.2.Alwaysusevirtualenvironmentsbyrunningpython3-mvenvmyproject_envandactivatewithsourcemyproject_env
