Linux如何查詢當前進程或線程的資源使用情況
在工作中,我們排除app出現(xiàn)的一些性能/資源問題時,通常要先知道當前app的資源使用情況,方能進一步思考改進措施。
獲取這些信息的途徑有很多,我這里簡單分享下兩種:
1)從proc文件系統(tǒng);
2)通過Linux 的API函數(shù)。
一、/proc/[PID]/下的各個文件
1、proc簡介
/proc 目錄是一個特殊的虛擬文件系統(tǒng),它提供了對內核運行時信息的訪問,包括進程、設備、網絡、文件系統(tǒng)等各個方面的信息。
它不是一個真正的文件系統(tǒng),而是基于內核數(shù)據結構的一個接口,通過這個接口可以獲取系統(tǒng)的運行時狀態(tài)。
下面是 /proc 目錄的一些重要子目錄和關鍵內容的說明:
- /proc/[PID]:此目錄以進程的 ID(PID)命名,并包含與該進程有關的文件和目錄,如之前所講的 /proc/pid/目錄。
- /proc/cpuinfo:該文件包含有關 CPU(處理器)的信息,如廠商、型號、頻率、緩存等。
- /proc/meminfo:該文件包含有關系統(tǒng)內存的信息,如總內存、可用內存、緩存、交換分區(qū)等。
- /proc/mounts:此文件列出了系統(tǒng)上已掛載的文件系統(tǒng),包括文件系統(tǒng)類型、掛載點、掛載選項等信息。
- /proc/net:此目錄包含有關網絡協(xié)議、接口和連接的信息,如 /proc/net/tcp、/proc/net/udp 等文件。
- /proc/sys:此目錄包含與內核參數(shù)和系統(tǒng)配置相關的文件??梢酝ㄟ^讀寫這些文件來修改內核的運行時行為。
- /proc/version:該文件包含了當前正在運行的內核版本信息。
- /proc/cmdline:此文件包含了系統(tǒng)引導時傳遞給內核的命令行參數(shù)。
- /proc/uptime:該文件包含自系統(tǒng)開機以來的運行時間和空閑時間。
- /proc/sys/kernel/hostname:此文件包含主機的名稱(hostname)。
除了上述目錄和文件,/proc 目錄下還有很多其他文件和目錄,涵蓋了系統(tǒng)和進程的各個方面的信息。
需要注意的是,/proc 目錄下的文件是動態(tài)生成的,信息在進程運行時改變。讀取這些文件時,請確保有足夠的權限,并理解每個文件的含義和用途。此外,不要輕易對 /proc 目錄下的文件進行修改,因為這可能會導致系統(tǒng)不穩(wěn)定或損壞。
2、/proc/[PID]/詳解

- arch_status: 該文件包含了有關進程所運行的指令集架構的信息。例如,它可以顯示進程在x86或ARM架構上運行。
- attr: 此目錄包含與進程關聯(lián)的文件、目錄和進程的訪問控制列表(ACL)信息。這些文件和目錄的訪問權限可以在這里進行管理和修改。
- autogroup: 這個文件顯示了進程是否被自動控制分組,以限制對CPU資源的訪問。如果進程分配給自動控制分組,則該文件中的值為"1";否則,為"0"。
- auxv: 此文件包含了進程的輔助向量信息,這些信息在加載動態(tài)鏈接器時向其傳遞參數(shù)。輔助向量為動態(tài)鏈接器提供有關進程環(huán)境和運行狀態(tài)的信息。
- cgroup: 該文件顯示了進程所屬的控制組(cgroup)的路徑??刂平M是一種組織和限制進程資源使用的方式。
- cmdline: 該文件包含了啟動進程時使用的命令行參數(shù),以null字符分隔各個參數(shù)??梢酝ㄟ^讀取該文件來獲取進程的命令行參數(shù)信息。
- comm: 進程的命令名可以通過這個文件獲得。它可以是可執(zhí)行文件名或進程自描述。
- coredump_filter:這個文件決定了進程在發(fā)生崩潰時生成核心轉儲(core dump)的內容。通過修改該文件的值,可以控制生成核心轉儲時包含的內容,這對于調試崩潰問題非常有用??梢允褂?echo 命令將特定的值寫入這個文件中,以修改核心轉儲的行為。
- cpu_resctrl_groups:這個文件是與 CPU 資源控制(Resource Control)相關的,用于管理進程對CPU資源的使用。通過這個文件,可以查詢或配置進程關聯(lián)的 CPU ResCtrl(CPU資源控制)組的信息。CPU資源控制是用于管理和限制進程對CPU資源的訪問的一種技術,可以實現(xiàn)資源隔離、分配和監(jiān)控。
- cwd: 這是一個符號鏈接,指向進程的當前工作目錄(current working directory)。
- environ: 該文件包含了進程的環(huán)境變量,以null字符分隔各個環(huán)境變量。通過讀取該文件,可以獲取進程的環(huán)境變量信息。
- cpuset: 這個文件包含了進程所屬的 cpuset(CPU affinity)的信息,可以用于管理進程所能使用的 CPU 核心。 通過這個文件,可以查詢或設置進程所在的 cpuset。
- exe:這是一個符號鏈接,指向進程正在執(zhí)行的可執(zhí)行文件。通過讀取這個符號鏈接,可以獲取進程當前正在執(zhí)行的可執(zhí)行文件的路徑。
- fdinfo: 這個目錄包含了關于進程打開的文件描述符(file descriptor)的詳細信息,如文件的偏移量(offset)等。
- gid_map:這個文件用于表示進程的實際組ID(GID)與其用戶命名空間中的GID之間的映射關系。
- io:這個文件包含了有關進程的輸入/輸出統(tǒng)計信息,如讀取和寫入的字節(jié)數(shù)、I/O操作次數(shù)等。
- limits:這個文件包含了對進程資源限制的報告,顯示了一些限制項目的值,比如內存限制、文件大小限制等。
- loginuid:這個文件記錄了與進程關聯(lián)的登錄用戶ID(login UID)。
- map_files:這個目錄包含了進程打開的映射文件的相關信息,可以用于查詢進程當前使用的文件映射情況。
- fd: 此目錄包含了進程打開的文件描述符(file descriptor)的符號鏈接??梢酝ㄟ^查看這些符號鏈接來獲取進程打開的文件等信息。
- maps: 該文件包含有關進程內存映射的信息,包括進程的內存地址范圍、映射的文件等。
- mounts: 此文件顯示了進程的掛載點信息,包括進程當前掛載的各個文件系統(tǒng)的詳細數(shù)據。
- mem:這個文件允許對進程的內存空間進行直接訪問,可以用于調試、內存分析等目的。
- mountinfo:這個文件提供了有關進程所掛載的文件系統(tǒng)的詳細信息,包括掛載點、掛載選項等。
- mountstats: 此文件包含了有關掛載點的統(tǒng)計信息,如 I/O 統(tǒng)計等。
- net:目錄包含了一系列與網絡相關的文件和子目錄,可以用于查詢進程的網絡連接、端口等信息。
- ns:這個目錄包含了進程的各種命名空間相關的符號鏈接,可以用于查詢和操作進程的命名空間。
- numa_maps:這個文件包含了有關進程內存使用和NUMA節(jié)點分布情況的信息,對于了解進程的NUMA相關性非常有用。
- oom_adj:這個文件包含了與進程的OOM(Out Of Memory)分級相關的信息,用于調整進程在內存不足情況下被系統(tǒng)殺死的優(yōu)先級。
- oom_score:這個文件包含了進程的OOM分數(shù),用于在系統(tǒng)內存不足時選擇性地終止進程。
- oom_score_adj:與 oom_adj 類似,這個文件也用于調整進程在內存不足情況下被系統(tǒng)殺死的優(yōu)先級。
- pagemap:這個文件提供了有關進程虛擬內存頁面到物理內存幀的映射信息,對于內存管理方面的深入了解非常有用。
- patch_state:這個文件包含了有關進程的內核安全補丁狀態(tài)的信息,通常用于安全審計和補丁管理。
- personality: 這個文件包含了與進程的運行環(huán)境和虛擬機架構相關的信息,用于指定進程的特定行為。
- projid_map:在用戶命名空間中使用的文件,用于表示進程實際項目ID(Project ID)與其用戶命名空間中的項目ID之間的映射關系。
- root:這是一個符號鏈接,指向進程的根目錄。
- sched:這個文件提供了與進程調度策略和優(yōu)先級相關的信息,包括當前調度策略、優(yōu)先級等。
- schedstat:這個文件包含了與進程調度統(tǒng)計相關的信息,如運行時間、等待時間等。
- sessionid:這個文件記錄了與進程關聯(lián)的會話ID。
- setgroups:這個文件包含了與進程的附加組(supplementary group)相關的信息。
- smaps:這個文件提供了詳細的進程內存映射信息,包括每個內存區(qū)域的權限、大小、映射文件等。
- smaps_rollup: 類似于 smaps 文件,但提供了按文件和庫合并的內存映射信息,用于更簡潔的內存分析。
- stack:這個文件記錄了進程的當前棧的內容。
- stat: 這個文件提供了與進程狀態(tài)相關的信息,如進程ID、父進程ID、運行狀態(tài)等。
- statm:這個文件提供了與進程內存使用量相關的信息,包括進程的總內存、共享內存、庫內存、堆內存等。
- status:這個文件提供了有關進程的多種信息,包括進程狀態(tài)、內存使用、文件描述符等。
- syscall:這個目錄包含與進程相關的系統(tǒng)調用信息,可以用于跟蹤和分析進程的系統(tǒng)調用。
- task:這個目錄包含了進程的所有線程(task)的信息。
- timens_offsets:這個文件提供了與進程關聯(lián)的時間命名空間偏移量的信息,用于跟蹤進程的時間命名空間變化。
- timers:這個目錄包含了與進程相關的定時器的信息,如定時器ID、時間值等。
- timerslack_ns:這個文件包含了與進程的定時器松弛值(timerslack)有關的信息,用于調整進程的定時行為。
- uid_map:這個文件用于表示進程的實際用戶ID(UID)與其用戶命名空間中的UID之間的映射關系。
- wchan:是一個用于描繪一個進程在等待什么的內核函數(shù)指針。它表示了進程當前正在等待的內核函數(shù)或系統(tǒng)調用??捎糜谡{試和分析進程的等待狀態(tài)。
這些文件和目錄提供了關于特定進程的多種信息,如進程狀態(tài)、資源使用情況、環(huán)境變量等,通常被用于性能調優(yōu)、調試以及資源管理方面,對于普通用戶來說可能并不經常需要直接操作這些文件。通過讀取這些文件,可以了解并監(jiān)視系統(tǒng)中各個進程的情況。請注意,有些文件是符號鏈接,需要使用readlink或ls -l等命令來獲取其指向的真實路徑。
知識補充:
命名空間(Namespace)在Linux系統(tǒng)中是一種用于隔離系統(tǒng)資源的機制。它允許在同一臺物理機上創(chuàng)建多個隔離的環(huán)境,每個環(huán)境可以擁有自己獨立的資源實例,例如進程ID、掛載點、網絡、用戶等。這種隔離使得不同的進程能夠在同一系統(tǒng)上運行,而彼此之間互不干擾。
在Linux中,有多種類型的命名空間,包括但不限于以下幾種:
- PID 命名空間(PID Namespace):使得進程擁有自己獨立的進程ID空間,進程在不同的PID命名空間中可以擁有相同的PID而不會相互影響。
- 掛載命名空間(Mount Namespace):使得進程擁有獨立的文件系統(tǒng)掛載點,不同的掛載命名空間中可以有不同的文件系統(tǒng)視圖。
- 網絡命名空間(Network Namespace):允許每個命名空間中擁有獨立的網絡設備、IP地址等網絡資源,實現(xiàn)網絡隔離。
- IPC 命名空間(IPC Namespace):用于隔離進程間通信資源,如消息隊列和共享內存等。
- UTS 命名空間(UTS Namespace):用于隔離系統(tǒng)標識,如主機名等。
- 用戶命名空間(User Namespace):允許分配不同的用戶和組ID給進程,從而實現(xiàn)用戶隔離。
通過使用命名空間,容器技術得以實現(xiàn),并且不同的容器可以在相互隔離的環(huán)境中運行,從而實現(xiàn)更高效的資源利用和更好的安全性。
二、通過Linux API獲取當前進程或線程的資源使用情況
要獲取當前進程或線程的資源使用情況,可以使用Linux提供的一些系統(tǒng)調用或API。
以下是一些常用的方法:
1、getrusage
getrusage 是一個用于獲取進程或線程的資源使用情況的系統(tǒng)調用函數(shù),在 Linux 系統(tǒng)中的頭文件 <sys/resource.h> 中定義。
#include <sys/time.h> #include <sys/resource.h> int getrusage(int who, struct rusage *usage);
參數(shù)who用于指定獲取資源使用情況的對象,包括以下兩個選項:
- RUSAGE_SELF: 獲取當前進程的資源使用情況。
- RUSAGE_CHILDREN: 獲取當前進程創(chuàng)建的所有子進程的資源使用情況的匯總信息。
參數(shù) usage 是一個指向 struct rusage 結構體的指針,用于存儲獲取到的資源使用情況信息。
//struct rusage 結構體包含了一系列字段,用于表示不同類型的資源使用情況
struct rusage {
struct timeval ru_utime; /* user CPU time used */
struct timeval ru_stime; /* system CPU time used */
long ru_maxrss; /* maximum resident set size */
long ru_ixrss; /* integral shared memory size */
long ru_idrss; /* integral unshared data size */
long ru_isrss; /* integral unshared stack size */
long ru_minflt; /* page reclaims (soft page faults) */
long ru_majflt; /* page faults (hard page faults) */
long ru_nswap; /* swaps */
long ru_inblock; /* block input operations */
long ru_oublock; /* block output operations */
long ru_msgsnd; /* IPC messages sent */
long ru_msgrcv; /* IPC messages received */
long ru_nsignals; /* signals received */
long ru_nvcsw; /* voluntary context switches */
long ru_nivcsw; /* involuntary context switches */
};
ru_utime:用戶級別的 CPU 時間(執(zhí)行用戶程序的時間)。ru_stime:系統(tǒng)級別的 CPU 時間(執(zhí)行系統(tǒng)調用的時間)。ru_maxrss:進程最大的常駐內存大?。ㄒ?KB 為單位)。ru_ixrss:進程的共享內存大小。ru_idrss:進程的非共享數(shù)據段的大小。ru_isrss:進程的棧大小。ru_minflt:產生的次缺頁錯誤(對不存在的內存頁面發(fā)生的訪問,需要從硬盤加載)。ru_majflt:產生的主缺頁錯誤(必須從硬盤加載數(shù)據)。ru_nswap:發(fā)生的交換次數(shù)(從內存到磁盤或反之)。ru_inblock:從塊設備讀取的次數(shù)。ru_oublock:向塊設備寫入的次數(shù)。ru_msgsnd:發(fā)送的消息數(shù)。ru_msgrcv:接收的消息數(shù)。ru_nsignals:發(fā)出的信號數(shù)。ru_nvcsw:從等待狀態(tài)喚醒的上下文切換次數(shù)(通過虛擬終端 I/O、文件系統(tǒng)路徑名查找、等待 CPU 時間等方式)。ru_nivcsw:無法滿足進程需求而導致的上下文切換次數(shù)。
這些資源使用情況信息對于進程性能分析和系統(tǒng)監(jiān)控非常有用。getrusage 函數(shù)返回的資源使用情況是關于當前進程或線程的信息。要獲取其他進程的資源使用情況,需要使用相應的進程相關的系統(tǒng)調用(如 wait4),并將返回的 rusage 結構體作為參數(shù)傳遞給 wait4。
wait4 是一個用于等待子進程結束并獲取其狀態(tài)信息的系統(tǒng)調用函數(shù)。在 Linux 系統(tǒng)中的頭文件 <sys/wait.h> 中定義。wait4 函數(shù)的原型為:
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
其中參數(shù)含義如下:
pid:指定要等待的子進程的 ID。傳入-1表示等待任意子進程結束。status:用于獲取子進程的退出狀態(tài)信息。options:用于指定等待的選項,包括一些控制子進程狀態(tài)獲取行為的選項。rusage:用于獲取子進程的資源使用情況信息,即上一條回答中提到的struct rusage結構體。
wait4 函數(shù)會阻塞父進程,直到指定的子進程結束。當子進程結束后,父進程將獲得子進程的退出狀態(tài)信息存儲在 status 中,并且如果傳入了 rusage 參數(shù),則會獲取子進程的資源使用情況信息。
通常情況下,wait4 函數(shù)與 fork 函數(shù)結合使用,父進程通過 fork 創(chuàng)建子進程,然后通過 wait4 等待子進程結束,并獲取其狀態(tài)信息。這樣可以實現(xiàn)父子進程之間的同步和協(xié)作。
#include <sys/resource.h>
int main() {
struct rusage usage;
getrusage(RUSAGE_SELF, &usage);
// 打印CPU時間
printf("CPU時間: %ld.%06ld 秒\n", usage.ru_utime.tv_sec, usage.ru_utime.tv_usec);
// 打印最大使用的內存
printf("最大內存使用量: %ld 字節(jié)\n", usage.ru_maxrss);
// 其他資源使用情況,可以在usage結構體中查看
// ...
return 0;
}
2、sysinfo
sysinfo 是一個用于獲取系統(tǒng)信息的系統(tǒng)調用函數(shù),在 Linux 系統(tǒng)中的頭文件 <sys/sysinfo.h> 中定義。
函數(shù)原型如下:
int sysinfo(struct sysinfo *info);
參數(shù) info 是一個指向 struct sysinfo 結構體的指針,用于存儲獲取到的系統(tǒng)信息。
//Since Linux 2.3.23 (i386) and Linux 2.3.48 (all architectures) the structure is:
struct sysinfo {
long uptime; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* Swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding to 64 bytes */
};
long uptime:系統(tǒng)已經運行的時間(以秒為單位)。unsigned long loads[3]:系統(tǒng)的平均負載值,分別代表過去1分鐘、5分鐘和15分鐘的平均負載。這些值是無符號長整型數(shù),表示了負載值乘以 2^16 的結果。unsigned long totalram:系統(tǒng)總共的物理內存大?。ㄒ宰止?jié)為單位)。unsigned long freeram:系統(tǒng)可用的物理內存大小(以字節(jié)為單位)。unsigned long sharedram:被共享的物理內存大小(以字節(jié)為單位)。unsigned long bufferram:被用作緩沖區(qū)的物理內存大小(以字節(jié)為單位)。unsigned long totalswap:交換空間的總大小(以字節(jié)為單位)。unsigned long freeswap:可用的交換空間大小(以字節(jié)為單位)。unsigned short procs:當前進程數(shù)量。unsigned long totalhigh:可用的高位內存大?。ㄒ宰止?jié)為單位)。unsigned long freehigh:空閑的高位內存大小(以字節(jié)為單位)。unsigned int mem_unit:內存單元大小(以字節(jié)為單位)。
sysinfo 函數(shù)的返回值為 0 表示成功,-1 表示失敗,并且可以通過 errno 來獲取具體錯誤信息。
#include <sys/sysinfo.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
struct sysinfo info;
sysinfo(&info);
// 打印總內存大小
printf("總內存大小: %ld 字節(jié)\n", info.totalram * info.mem_unit);
// 打印已使用內存大小
printf("已使用內存大小: %ld 字節(jié)\n", (info.totalram - info.freeram) * info.mem_unit);
// 其他資源使用情況,可以在info結構體中查看
// ...
return 0;
}
在struct sysinfo 結構體中,loads 數(shù)組中的數(shù)值表示了負載值乘以 2^16 的結果,這是因為 sysinfo 結構體中的 loads 數(shù)組使用了 unsigned long 類型。
在 Linux 內核中,負載值是以固定點數(shù)的格式表示的,使用了定點數(shù)表示方式來保留小數(shù)部分。在這里,每個負載值都被乘以了 2^16(65536),以便將小數(shù)部分轉換為整數(shù)。
這種表示方式的好處在于,它可以比較精確地表示系統(tǒng)的負載情況,同時又不需要使用浮點數(shù)來表示,因為浮點數(shù)的運算會耗費相對更多的 CPU 時間。通過將負載值乘以一個固定的倍數(shù)(2^16),可以在不犧牲太多精度的情況下,使用整數(shù)進行表示和計算,這樣會更高效。
當我們從 struct sysinfo 結構體中獲取負載值時,需要將其除以 2^16 來得到真實的負載值。例如,在上面的示例代碼中,打印負載值時并沒有除以 2^16,因此實際的負載值應當是 info.loads[x] / 65536 才能得到系統(tǒng)的實際負載情況。
總之,通過將負載值乘以 2^16 來表示,Linux 內核可以在保持較高精度的同時,使用更高效的整數(shù)表示方式,用于存儲和計算系統(tǒng)的負載情況。
3、times
times 函數(shù)是一個用于獲取進程和子進程的系統(tǒng)和用戶 CPU 時間的系統(tǒng)調用,其原型如下:
#include <sys/times.h> clock_t times(struct tms *buf);
buf是一個指向tms結構的指針,它用來存儲 CPU 時間的信息。
struct tms 結構包含了進程和子進程的 CPU 時間信息,其定義如下:
struct tms {
clock_t tms_utime; // 進程在用戶態(tài)花費的時間
clock_t tms_stime; // 進程在內核態(tài)花費的時間
clock_t tms_cutime; // 所有已終止子進程在用戶態(tài)花費的時間
clock_t tms_cstime; // 所有已終止子進程在內核態(tài)花費的時間
};
tms_utime表示進程在用戶態(tài)花費的 CPU 時間。tms_stime表示進程在內核態(tài)花費的 CPU 時間。tms_cutime表示所有已終止子進程在用戶態(tài)花費的 CPU 時間。tms_cstime表示所有已終止子進程在內核態(tài)花費的 CPU 時間。
示例代碼如下所示,演示了如何使用 times 函數(shù)來獲取進程的 CPU 時間信息:
#include <stdio.h>
#include <sys/times.h>
#include <time.h>
#include <unistd.h>
int main() {
struct tms tms_buf;
clock_t start, end;
// 獲取起始時間
start = times(&tms_buf);
printf("Starting time: %ld\n", start);
// 模擬一些工作
for (int i = 0; i < 100000000; ++i) {
// do something
}
// 獲取結束時間
end = times(&tms_buf);
printf("Ending time: %ld\n", end);
// 計算 CPU 時間消耗
clock_t user_time = tms_buf.tms_utime;
clock_t sys_time = tms_buf.tms_stime;
printf("User CPU time: %ld\n", user_time);
printf("System CPU time: %ld\n", sys_time);
return 0;
}
這個示例代碼中,我們首先調用 times 函數(shù)獲取了進程的 CPU 時間信息,并輸出了起始時間。然后進行了一些模擬工作,之后再次調用 times 函數(shù)獲取了結束時間,最后計算了用戶態(tài)和內核態(tài)的 CPU 時間消耗。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
Centos 6和Centos 7下服務啟動方法及添加到開機啟動項的方法
這篇文章主要介紹了Centos 6和Centos 7下服務啟動方法及添加到開機啟動項的方法的相關資料,需要的朋友可以參考下2016-10-10
關于linux分區(qū),文件系統(tǒng),目錄結構的概述
下面小編就為大家?guī)硪黄P于linux分區(qū),文件系統(tǒng),目錄結構的概述。小編覺得挺不錯的?,F(xiàn)在就分享給大家。也給大家做個參考。一起跟隨小編過來看看吧2016-12-12
nacos在linux下啟動startup.sh報錯問題及解決
遇到Nacos啟動錯誤提示“Permission denied”,可通過執(zhí)行命令chmod u+x *.sh給予startup.sh執(zhí)行權限,解決權限問題,啟動成功,這是一種常見的解決Linux下腳本執(zhí)行權限問題的方法2023-03-03

