首页 > 系统相关 >Linux中检测进程/程序的资源使用情况(CPU、内存等)

Linux中检测进程/程序的资源使用情况(CPU、内存等)

时间:2022-10-08 16:47:52浏览次数:86  
标签:20 0.0 top jackie 内存 str Linux CPU

Linux top 工具中各字段的含义:

top输出信息:

jackie@jackie-lenovo:~$ top
top - 09:19:00 up 2 days, 14:46,  5 users,  load average: 0.46, 0.57, 0.48
Tasks: 621 total,   1 running, 537 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.5 us,  0.8 sy,  0.0 ni, 94.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16334368 total,  6160820 free,  2904640 used,  7268908 buff/cache
KiB Swap: 31249404 total, 30721732 free,   527672 used. 12812168 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
 4030 root      20   0  428892  59252  27560 S  45.5  0.4   7:30.01 sunloginclient
14838 root      20   0  484592  80636  44664 S   8.0  0.5 128:57.32 Xorg
  934 root      20   0 1162808   6916   4408 S   3.3  0.0  74:52.88 sunloginclient
14865 root     -51   0       0      0      0 S   2.7  0.0  36:43.09 irq/132-nvidia
22985 jackie    20   0 1057640  41444  27464 S   2.3  0.3  63:40.92 sunloginclient
 4732 jackie    20   0 36.441g 146728  58072 S   1.0  0.9   7:24.02 code
 4472 jackie    20   0  681180 144304  74592 S   0.7  0.9   7:29.98 code
 7820 jackie    20   0   20392   4404   3060 S   0.7  0.0  16:49.75 htop
  339 jackie    20   0  968128  93868  33804 S   0.3  0.6   0:10.31 node
  930 root      20   0  125636     40     40 S   0.3  0.0   8:26.13 oray_rundaemon
 1195 root      20   0 1218680   5676    864 S   0.3  0.0   8:27.24 containerd
 3839 jackie    20   0 1076996 202932  35944 S   0.3  1.2   0:20.31 node
 7628 jackie    20   0  775140  57340  35084 S   0.3  0.4   1:26.83 /usr/bin/x-term
 7862 jackie    20   0   35848   4152   3076 R   0.3  0.0   0:00.03 top
 8093 jackie    20   0 32.762g 195008 118932 S   0.3  1.2   1:10.97 chrome
22808 jackie    20   0 1732096 157504  56712 S   0.3  1.0   7:45.26 compiz
    1 root      20   0  185268   5284   3696 S   0.0  0.0   0:02.73 systemd
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.05 kthreadd
    4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 kworker/0:0H
    6 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 mm_percpu_wq
...

第1行解释:

top - 09:19:00 up 2 days, 14:46,  5 users,  load average: 0.46, 0.57, 0.48
字段 含义
09:19:00 系统当前时间
up 2 days, 14:46 系统运行时间。本机已运行2天14小时46分钟
5 users 当前登录了5个用户
load average: 0.46, 0.57, 0.48 系统在之前 1 分钟、5 分钟、15 分钟的平均负载。如果 CPU 是单核的,则这个数值超过 1 就是高负载;如果 CPU 是四核的,则这个数值超过 4 就是高负载 ;(这个平均负载完全是依据个人经验来进行判断的,一般认为不应该超过服务器 CPU 的核数)

第2行解释:

Tasks: 621 total,   1 running, 537 sleeping,   0 stopped,   0 zombie
字段 含义
621 total 系统中的进程总数
1 running 正在运行的进程数
537 sleeping 睡眠的进程数
0 stopped 停止的进程数
0 zombie 僵尸进程数。如果不是 0,则需要手工检查僵尸进程

第3行解释:

%Cpu(s):  4.5 us,  0.8 sy,  0.0 ni, 94.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
字段 含义
4.5 us, 用户模式占用的 CPU 百分比。表示的是所有用户进程占用整个cpu的平均值,由于每个核心占用的百分比不同,所以按平均值来算比较有参考意义。参考
0.8 sy, 系统模式占用的 CPU 百分比
0.0 ni, 改变过优先级的用户进程占用的 CPU 百分比
94.7 id, 空闲 CPU 占用的 CPU 百分比
0.0 wa, 等待输入/输出的进程占用的 CPU 百分比
0.0 hi, 硬中断请求服务占用的 CPU 百分比
0.0 si, 软中断请求服务占用的 CPU 百分比
0.0 st st(steal time)意为虚拟时间百分比,就是当有虚拟机时,虚拟 CPU 等待实际 CPU 的时间百分比

第4行解释:

KiB Mem : 16334368 total,  6160820 free,  2904640 used,  7268908 buff/cache
字段 含义
16334368 total, 物理内存的总量,单位为KB
6160820 free, 空闲的物理内存数量
2904640 used, 己经使用的物理内存数量
7268908 buff/cache 作为缓冲/缓存的内存数量。 简单来说,缓存(cache)是用来加速数据从硬盘中"读取"的,而缓冲(buffer)是用来加速数据"写入"硬盘的。

第5行解释:

KiB Swap: 31249404 total, 30721732 free,   527672 used. 12812168 avail Mem
字段 含义
KiB Swap: 31249404 total, 交换分区(虚拟内存)的总大小
30721732 free, 空闲交换分区的大小
527672 used. 已经使用的交换分区的大小
12812168 avail Mem 作为缓存的交换分区的大小

第6行解释:

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
字段 含义
PID 进程的 ID
USER 该进程所属的用户。
PR 优先级,数值越小优先级越高。
NI Nice值的范围从-20到+19(不同系统的值范围是不一样的),正值表示低优先级,负值表示高优先级,值为零则表示不会调整该进程的优先级。
VIRT 进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
RES 进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
SHR 共享内存大小,单位kb
S 进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
%CPU 上次更新到现在的CPU时间占用百分比。%CPU显示的是进程占用一个核的百分比,而不是整个cpu(所有核心)的百分比,有时候可能大于100,那是因为该进程启用了多线程占用了多个核心,所以有时候我们看该值得时候会超过100%,但不会超过总核数*100。
%MEM 进程使用的物理内存百分比 ,“RES” is the memory consumed by the process in RAM, and “%MEM” expresses this value as a percentage of the total RAM available. 参考
TIME+ 该进程共占用的 CPU 时间。TIME+是指的进程所使用的CPU时间,不是进程启动到现在的时间,因此,如果一个进程使用的cpu很少,那即使这个进程已经存在N长时间,TIME+也是很小的数值。此外,如果你的系统有多个CPU,或者是多核CPU的话,那么,进程占用多个cpu的时间是累加的。例如:2:32.45表示该进程共占用了2分钟 + 30秒 + 十分之4秒 + 百分之5秒的时间。 参考
COMMAND 进程名称(命令名/命令行)

参考资料:

  1. Linux top命令详解:持续监听进程运行状态

  2. Linux top命令的用法详细详解

  3. A Guide to the Linux “Top” Command

  4. Linux top命令里面%CPU和cpu(s)的差别

  5. [linux top 中的time+]

  6. top这个命令在统计存在多线程和共享内存的进程的资源时,确实存在缺陷

LInux top常见命令展示

默认命令:top

jackie@jackie-lenovo:~$ top
top - 15:08:10 up 4 days, 20:35,  4 users,  load average: 0.85, 0.86, 1.23
Tasks: 370 total,   1 running, 275 sleeping,   8 stopped,   3 zombie
%Cpu(s):  3.7 us,  0.7 sy,  0.0 ni, 95.4 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16334368 total,  5885400 free,  3787396 used,  6661572 buff/cache
KiB Swap: 31249404 total, 30699972 free,   549432 used. 11897564 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
17406 root      20   0  494428  57260  27452 S  50.0  0.4 154:33.15 sunloginclient
14838 root      20   0  524608 112368  44232 S  12.5  0.7 291:02.84 Xorg
 9660 jackie    20   0   35584   3932   3120 R   6.2  0.0   0:00.01 top
    1 root      20   0  186308   6292   3676 S   0.0  0.0   0:08.28 systemd
    2 root      20   0       0      0      0 S   0.0  0.0   0:00.08 kthreadd
    4 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 kworker/0:0H
    6 root       0 -20       0      0      0 I   0.0  0.0   0:00.00 mm_percpu_wq
...
以上区域重复刷新

Bath-mode 命令:top -b 有利于后期的文本处理

top - 15:17:15 up 4 days, 20:44,  4 users,  load average: 0.62, 0.78, 1.01
Tasks: 371 total,   2 running, 275 sleeping,   8 stopped,   3 zombie
%Cpu(s):  3.7 us,  0.7 sy,  0.0 ni, 95.4 id,  0.1 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16334368 total,  5848800 free,  3790312 used,  6695256 buff/cache
KiB Swap: 31249404 total, 30700228 free,   549176 used. 11894536 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
17406 root      20   0  494428  56784  27452 S  37.5  0.3 158:43.97 sunloginclient
 9849 jackie    20   0   35436   3804   3260 R   6.2  0.0   0:00.02 top
...
29531 jackie    20   0  354712   4060   3536 S   0.0  0.0   0:00.03 gvfsd-network
29581 jackie    20   0  363452   1116   1016 S   0.0  0.0   0:00.38 gvfsd-dnssd

top - 15:17:18 up 4 days, 20:44,  4 users,  load average: 0.57, 0.77, 1.01
Tasks: 371 total,   2 running, 275 sleeping,   8 stopped,   3 zombie
%Cpu(s):  4.6 us,  0.8 sy,  0.0 ni, 94.6 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16334368 total,  5848360 free,  3790808 used,  6695200 buff/cache
KiB Swap: 31249404 total, 30700228 free,   549176 used. 11894096 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
17406 root      20   0  494428  56784  27452 S  46.4  0.3 158:45.38 sunloginclient
14838 root      20   0  524608 112368  44232 S   7.2  0.7 291:44.30 Xorg
...
29531 jackie    20   0  354712   4060   3536 S   0.0  0.0   0:00.03 gvfsd-network
29581 jackie    20   0  363452   1116   1016 S   0.0  0.0   0:00.38 gvfsd-dnssd

...
新文本会不断追加,而非在固定区域内重复刷新,这有利于将其保存到文件中做进一步数据处理

正则表达式:top -b | grep -E "top"筛选出含某个字符串的行

jackie@jackie-lenovo:~$ top -b | grep -E "top"
top - 15:26:25 up 4 days, 20:53,  4 users,  load average: 0.94, 0.78, 0.91
Tasks: 372 total,   1 running, 277 sleeping,   8 stopped,   3 zombie
 9948 jackie    20   0   35436   3736   3192 R   6.2  0.0   0:00.01 top
 5597 jackie    20   0   34564   3284   2976 T   0.0  0.0   0:00.00 top
 5611 jackie    20   0   34564   3264   2960 T   0.0  0.0   0:00.00 top
 9666 jackie    20   0   35560   4040   3196 S   0.0  0.0   0:03.43 top
13477 jackie    20   0   34564   3332   3020 T   0.0  0.0   0:00.00 top
14659 jackie    20   0   20248   4432   2964 S   0.0  0.0  14:31.35 htop
top - 15:26:28 up 4 days, 20:53,  4 users,  load average: 0.94, 0.78, 0.91
Tasks: 372 total,   1 running, 277 sleeping,   8 stopped,   3 zombie
14659 jackie    20   0   20248   4432   2964 S   1.0  0.0  14:31.38 htop
 9666 jackie    20   0   35560   4040   3196 S   0.3  0.0   0:03.44 top
 9948 jackie    20   0   35436   3736   3192 R   0.3  0.0   0:00.02 top
 5597 jackie    20   0   34564   3284   2976 T   0.0  0.0   0:00.00 top
 5611 jackie    20   0   34564   3264   2960 T   0.0  0.0   0:00.00 top
13477 jackie    20   0   34564   3332   3020 T   0.0  0.0   0:00.00 top
...

正则表达式:top -b | grep -E "\<top\>"精确筛含特定单词的行

jackie@jackie-lenovo:~$ top -b | grep -E "\<top\>"
top - 15:32:56 up 4 days, 21:00,  4 users,  load average: 1.07, 0.80, 0.86
10884 jackie    20   0   35436   3660   3120 R  11.8  0.0   0:00.02 top
 5597 jackie    20   0   34564   3284   2976 T   0.0  0.0   0:00.00 top
 5611 jackie    20   0   34564   3264   2960 T   0.0  0.0   0:00.00 top
13477 jackie    20   0   34564   3332   3020 T   0.0  0.0   0:00.00 top

正则表达式:top -b | grep -E "jackie.*?top"筛同时含串1和串2的行

jackie@jackie-lenovo:~$ top -b | grep -E "jackie.*?top"
 5597 jackie    20   0   34564   3284   2976 T   0.0  0.0   0:00.00 top
 5611 jackie    20   0   34564   3264   2960 T   0.0  0.0   0:00.00 top
13477 jackie    20   0   34564   3332   3020 T   0.0  0.0   0:00.00 top
13525 jackie    20   0   35436   3724   3172 R   0.0  0.0   0:00.00 top
14659 jackie    20   0   20248   4432   2964 S   0.0  0.0  14:43.92 htop

其中,【.*?】表示任意多个任意字符

正则表达式:top -b | grep -E "top|front"筛含字符串1或字符串2的行

jackie@jackie-lenovo:~$ top -b | grep -E "top|front"
top - 15:36:19 up 4 days, 21:03,  4 users,  load average: 1.55, 1.11, 0.97
Tasks: 377 total,   2 running, 282 sleeping,   8 stopped,   3 zombie
11936 jackie    20   0   35436   3804   3260 R   6.2  0.0   0:00.01 top
 5597 jackie    20   0   34564   3284   2976 T   0.0  0.0   0:00.00 top
 5611 jackie    20   0   34564   3264   2960 T   0.0  0.0   0:00.00 top
10057 jackie    20   0  790928 239680  33956 S   0.0  1.5   1:01.70 front_end_node
13477 jackie    20   0   34564   3332   3020 T   0.0  0.0   0:00.00 top
14659 jackie    20   0   20248   4432   2964 S   0.0  0.0  14:40.39 htop

控制更新次数: top -n 3 -b | grep -E "front" 更新三次后停止

jackie@jackie-lenovo:~$ top -n 3 -b | grep -E "front"
10057 jackie    20   0  841572 265916  33956 S   0.0  1.6   3:50.67 front_end_node
10057 jackie    20   0  841744 265976  33956 S  19.9  1.6   3:51.27 front_end_node
10057 jackie    20   0  841744 265976  33956 S  14.3  1.6   3:51.70 front_end_node

控制更新周期:top -d 1 -b | grep -E "front"1秒更新一次(默认周期3秒)

jackie@jackie-lenovo:~$ top -d 1 -b | grep -E "front"
10057 jackie    20   0  863648 278540  33956 S  93.8  1.7   4:05.10 front_end_node
10057 jackie    20   0  863648 278540  33956 S  14.9  1.7   4:05.25 front_end_node
10057 jackie    20   0  863712 278564  33956 R  21.8  1.7   4:05.47 front_end_node
10057 jackie    20   0  863712 278564  33956 S  28.7  1.7   4:05.76 front_end_node
10057 jackie    20   0  931008 317888  33956 R  18.0  1.9   4:05.94 front_end_node
...

利用C++调用top的shell命令然后解析:便于提取和处理数据

代码部分

#include <stdio.h>
#include <cstring>
#include <unistd.h>

#include <iostream>
#include <fstream>
#include <list>
#include <sstream>
#include <chrono>

// http://c.biancheng.net/view/1065.html
// https://www.jb51.net/article/40807.htm
// https://www.jianshu.com/p/3c078505fffa

struct TOP1HeaderInfo
{
    // 12:26:46	系统当前时间
    int system_time_hh = 0;
    int system_time_mm = 0;
    int system_time_ss = 0;

    // up 1 day, 13:32	系统的运行时间.本机己经运行 1 天 13 小时 32 分钟
    int system_runing_time_dd = 0;
    int system_runing_time_hh = 0;
    int system_runing_time_mm = 0;

    // 2 users	当前登录了两个用户
    int num_users = 0;

    // load average: 0.00,0.00,0.00
    // 系统在之前 1 分钟、5 分钟、15 分钟的平均负载。
    // 如果 CPU 是单核的,则这个数值超过 1 就是高负载:
    // 如果 CPU 是四核的,则这个数值超过 4 就是高负载
    //(这个平均负载完全是依据个人经验来进行判断的,一般认为不应该超过服务器 CPU 的核数)
    double load_average_1minuts = 0.0;
    double load_average_5minuts = 0.0;
    double load_average_15minuts = 0.0;
};

struct TOP2TasksInfo
{
    // Tasks: 95 total	系统中的进程总数
    int total_tasks = 0;
    // 1 running	正在运行的进程数
    int running_tasks = 0;
    // 94 sleeping	睡眠的进程数
    int sleeping_tasks = 0;
    // 0 stopped	正在停止的进程数
    int stopped_tasks = 0;
    // 0 zombie	僵尸进程数。如果不是 0,则需要手工检查僵尸进程
    int zombie_tasks = 0;
};

struct TOP3CPUInfo
{
    // %Cpu(s): 0.1 us	用户模式占用的 CPU 百分比
    double percent_us = 0.0;
    // 0.1 sy	系统模式占用的 CPU 百分比
    double percent_sy = 0.0;
    // 0.0 ni	改变过优先级的用户进程占用的 CPU 百分比
    double percent_ni = 0.0;
    // 99.7 id	空闲 CPU 占用的 CPU 百分比
    double percent_id = 0.0;
    // 0.1 wa	等待输入/输出的进程占用的 CPU 百分比
    double percent_wa = 0.0;
    // 0.0 hi	硬中断请求服务占用的 CPU 百分比
    double percent_hi = 0.0;
    // 0.1 si	软中断请求服务占用的 CPU 百分比
    double percent_si = 0.0;
    // 0.0 st	st(steal time)意为虚拟时间百分比,就是当有虚拟机时,虚拟 CPU 等待实际 CPU 的时间百分比
    double percent_st = 0.0;
};

struct TOP4MemoryInfo
{
    // KiB Mem : 16334368 total, 物理内存的总量,单位为KB
    double memery_total = 0.0;
    // 4251264 free, 空闲的物理内存数量
    double memery_free = 0.0;
    // 5003964 used, 己经使用的物理内存数量
    double memery_used = 0.0;
    // 7079140 buff/cache  作为缓冲的内存数量
    double memery_buff_cache = 0.0;
};

struct TOP5SwapInfo
{
    // KiB Swap: 31249404 total, 交换分区(虚拟内存)的总大小
    double swap_total = 0.0;
    // 30703044 free, 空闲交换分区的大小
    double swap_free = 0.0;
    // 546360 used. 已经使用的交换分区的大小
    double swap_used = 0.0;
    // 10721664 avail Mem 作为缓存的交换分区的大小
    double swap_available = 0.0;
};

struct TOP6ProcessInfo
{
public:
    // PID:进程的 ID。
    int process_PID = 0;
    // USER:该进程所属的用户。
    std::string process_USER = "";
    // PR:优先级,数值越小优先级越高。
    std::string process_PR = "";
    // NI:Nice值的范围从-20到+19(不同系统的值范围是不一样的),
    // 正值表示低优先级,负值表示高优先级,值为零则表示不会调整该进程的优先级。
    int process_NI = 0;
    // VIRT:进程使用的虚拟内存总量,单位kb。VIRT=SWAP+RES
    double process_VIRT = 0;
    // RES:进程使用的、未被换出的物理内存大小,单位kb。RES=CODE+DATA
    double process_RES = 0;
    // SHR:共享内存大小,单位为 KB。
    double process_SHR = 0;
    // S:进程状态。D=不可中断的睡眠状态 R=运行 S=睡眠 T=跟踪/停止 Z=僵尸进程
    std::string process_S = "";
    // %CPU:该进程占用 CPU 的百分比。
    double process_percentageCPU = 0.0;
    // %MEM:该进程占用内存的百分比。
    double process_percentageMEM = 0.0;
    // TIME+:该进程共占用的 CPU 时间。
    std::string process_TIMEPlus = "";
    // COMMAND:进程的命令名。
    std::string process_COMMAND = "";
};

class TOPParser
{
public:
    TOPParser(std::string top_shell_cmd);

    bool updateAllInfo();

    std::list<TOP6ProcessInfo> getAllProcessInfo();
    TOP1HeaderInfo getHeaderInfo();

private:
    void executeCMD(const char *cmd, char *result);
    bool update1HeaderInfo(std::string str_info);
    bool update2TasksInfo(std::string str_info);
    bool update3CPUInfo(std::string str_info);
    bool update4MemoryInfo(std::string str_info);
    bool update5SwapInfo(std::string str_info);
    bool update6ProcessInfo(std::string str_info);

private:
    std::string m_top_shell_cmd = "";
    TOP1HeaderInfo m_1header_info;
    TOP2TasksInfo m_2tasks_info;
    TOP3CPUInfo m_3cpu_info;
    TOP4MemoryInfo m_4memory_info;
    TOP5SwapInfo m_5swap_info;
    std::list<TOP6ProcessInfo> m_list_6process_info;
};

TOPParser::TOPParser(std::string top_shell_cmd)
    : m_top_shell_cmd(top_shell_cmd)
{
}

std::list<TOP6ProcessInfo> TOPParser::getAllProcessInfo()
{
    return m_list_6process_info;
}

TOP1HeaderInfo TOPParser::getHeaderInfo()
{
    return m_1header_info;
}

bool TOPParser::updateAllInfo()
{
    char result[10000] = "";
    executeCMD(m_top_shell_cmd.c_str(), result);

    std::string result_shell(result);
    // std::cout << result_shell << std::endl;

    //  寻找第二个top信息块的位置
    size_t index0 = result_shell.find("top - ", 0);
    size_t index1 = result_shell.find("top - ", ++index0);
    size_t index2 = result_shell.find("top - ", ++index1);
    // std::cout << "index0:" << index0 << " index1:" << index1 << " index2:" << index2 << std::endl;

    if (index0 == std::string::npos ||
        index1 == std::string::npos ||
        index2 == std::string::npos)
    {
        return false;
    }

    //  获取第二个top信息块字符串
    std::string str_tmp2 = result_shell.substr(index1 - 1, index2 - index1 + 1);
    // std::cout << str_tmp2 << std::endl
    //           << "updateAllInfo------------" << std::endl;

    return (update6ProcessInfo(str_tmp2) &&
            update1HeaderInfo(str_tmp2) &&
            update2TasksInfo(str_tmp2) &&
            update3CPUInfo(str_tmp2) &&
            update4MemoryInfo(str_tmp2) &&
            update5SwapInfo(str_tmp2));
}

bool TOPParser::update1HeaderInfo(std::string str_info)
{
    size_t index0 = str_info.find("top - ", 0);
    size_t index1 = str_info.find("\n", index0);
    if (index0 != std::string::npos &&
        index1 != std::string::npos)
    {
        std::string str_1header_info = str_info.substr(index0, index1 - index0 + 1);
        // std::cout << str_1header_info << std::endl
        //           << "update1HeaderInfo---------";

        int ret = sscanf(str_1header_info.c_str(),
                         "top - %d:%d:%d up %d days, %d:%d,  %d users,  load average: %lf, %lf, %lf",
                         &m_1header_info.system_time_hh,
                         &m_1header_info.system_time_mm,
                         &m_1header_info.system_time_ss,
                         &m_1header_info.system_runing_time_dd,
                         &m_1header_info.system_runing_time_hh,
                         &m_1header_info.system_runing_time_mm,
                         &m_1header_info.num_users,
                         &m_1header_info.load_average_1minuts,
                         &m_1header_info.load_average_5minuts,
                         &m_1header_info.load_average_15minuts);

        // std::cout << m_1header_info.system_time_hh << " "
        //           << m_1header_info.system_time_mm << " "
        //           << m_1header_info.system_time_ss << " "
        //           << m_1header_info.system_runing_time_dd << " "
        //           << m_1header_info.system_runing_time_hh << " "
        //           << m_1header_info.system_runing_time_mm << " "
        //           << m_1header_info.num_users << " "
        //           << m_1header_info.load_average_1minuts << " "
        //           << m_1header_info.load_average_5minuts << " "
        //           << m_1header_info.load_average_15minuts << " "
        //           << std::endl;

        if (ret != 10)
        {
            return false;
        }
    }
    else
    {
        std::cerr << "update1HeaderInfo(): failed" << std::endl;

        return false;
    }

    return true;
}

bool TOPParser::update2TasksInfo(std::string str_info)
{
    size_t index0 = str_info.find("Tasks:", 0);
    size_t index1 = str_info.find("\n", index0);
    if (index0 != std::string::npos &&
        index1 != std::string::npos)
    {
        std::string str_2tasks_info = str_info.substr(index0, index1 - index0 + 1);
        // std::cout << str_2tasks_info << std::endl
        //           << "update2TasksInfo-------------";

        int ret = sscanf(str_2tasks_info.c_str(),
                         "Tasks: %d total,   %d running, %d sleeping,   %d stopped,   %d zombie",
                         &m_2tasks_info.total_tasks,
                         &m_2tasks_info.running_tasks,
                         &m_2tasks_info.sleeping_tasks,
                         &m_2tasks_info.stopped_tasks,
                         &m_2tasks_info.zombie_tasks);

        // std::cout << m_2tasks_info.total_tasks << " "
        //           << m_2tasks_info.running_tasks << " "
        //           << m_2tasks_info.sleeping_tasks << " "
        //           << m_2tasks_info.stopped_tasks << " "
        //           << m_2tasks_info.zombie_tasks << " "
        //           << std::endl;

        if (ret != 5)
        {
            std::cout << "ret:" << ret << std::endl;
            return false;
        }

        return true;
    }
    else
    {
        std::cerr << "update2TasksInfo(): failed" << std::endl;

        return false;
    }
}

bool TOPParser::update3CPUInfo(std::string str_info)
{
    size_t index0 = str_info.find("\%Cpu(s):", 0);
    size_t index1 = str_info.find("\n", index0);
    if (index0 != std::string::npos &&
        index1 != std::string::npos)
    {
        std::string str_3cpu_info = str_info.substr(index0, index1 - index0 + 1);
        // std::cout << str_3cpu_info << std::endl
        //           << "update3CPUInfo------------";

        int ret = sscanf(str_3cpu_info.c_str(),
                         "%%Cpu(s):  %lf us,  %lf sy,  %lf ni, %lf id,  %lf wa,  %lf hi,  %lf si,  %lf st",
                         &m_3cpu_info.percent_us,
                         &m_3cpu_info.percent_sy,
                         &m_3cpu_info.percent_ni,
                         &m_3cpu_info.percent_id,
                         &m_3cpu_info.percent_wa,
                         &m_3cpu_info.percent_hi,
                         &m_3cpu_info.percent_si,
                         &m_3cpu_info.percent_st);

        // std::cout << m_3cpu_info.percent_us << " "
        //           << m_3cpu_info.percent_sy << " "
        //           << m_3cpu_info.percent_ni << " "
        //           << m_3cpu_info.percent_id << " "
        //           << m_3cpu_info.percent_wa << " "
        //           << m_3cpu_info.percent_hi << " "
        //           << m_3cpu_info.percent_si << " "
        //           << m_3cpu_info.percent_st << " "
        //           << std::endl;

        if (ret != 8)
        {
            return false;
        }
    }
    else
    {
        std::cerr << "update3CPUInfo(): failed" << std::endl;

        return false;
    }

    return true;
}

bool TOPParser::update4MemoryInfo(std::string str_info)
{
    size_t index0 = str_info.find("KiB Mem :", 0);
    size_t index1 = str_info.find("\n", index0);

    if (index0 != std::string::npos &&
        index1 != std::string::npos)
    {
        std::string str_4memory_info = str_info.substr(index0, index1 - index0 + 1);
        // std::cout << str_4memory_info << std::endl
        //           << "update4MemoryInfo----------" << std::endl;

        int ret = sscanf(str_4memory_info.c_str(),
                         "KiB Mem : %lf total,   %lf free,  %lf used, %lf buff/cache",
                         &m_4memory_info.memery_total,
                         &m_4memory_info.memery_free,
                         &m_4memory_info.memery_used,
                         &m_4memory_info.memery_buff_cache);

        // std::cout << m_4memory_info.memery_total << " "
        //           << m_4memory_info.memery_free << " "
        //           << m_4memory_info.memery_used << " "
        //           << m_4memory_info.memery_buff_cache << " "
        //           << std::endl;

        if (ret != 4)
        {
            return false;
        }

        return true;
    }
    else
    {
        std::cerr << "update4MemoryInfo(): failed" << std::endl;

        return false;
    }
}

bool TOPParser::update5SwapInfo(std::string str_info)
{
    size_t index0 = str_info.find("KiB Swap:", 0);
    size_t index1 = str_info.find("\n", index0);

    if (index0 != std::string::npos &&
        index1 != std::string::npos)
    {
        std::string str_5swap_info = str_info.substr(index0, index1 - index0 + 1);
        // std::cout << str_5swap_info << std::endl
        //           << "update5SwapInfo"
        //           << "----------------" << std::endl;

        int ret = sscanf(str_5swap_info.c_str(),
                         "KiB Swap: %lf total, %lf free,   %lf used. %lf avail Mem",
                         &m_5swap_info.swap_total,
                         &m_5swap_info.swap_free,
                         &m_5swap_info.swap_used,
                         &m_5swap_info.swap_available);

        // std::cout << m_5swap_info.swap_total << " "
        //           << m_5swap_info.swap_free << " "
        //           << m_5swap_info.swap_used << " "
        //           << m_5swap_info.swap_available << " "
        //           << std::endl;

        if (ret != 4)
        {
            return false;
        }
    }
    else
    {
        std::cerr << "update5SwapInfo(): failed" << std::endl;

        return false;
    }

    return true;
}

bool TOPParser::update6ProcessInfo(std::string str_info)
{
    // 寻找目标字符串中进程信息的行数(依据状态符号:D、R、S、T、Z五种状态)
    size_t index_D = 0;
    std::list<size_t> list_indexes;
    while ((index_D = str_info.find(" D ", index_D)) != std::string::npos)
    {
        list_indexes.push_back(index_D);

        index_D++;
    }
    //
    size_t index_R = 0;
    while ((index_R = str_info.find(" R ", index_R)) != std::string::npos)
    {
        list_indexes.push_back(index_R);

        index_R++;
    }
    //
    size_t index_S = 0;
    while ((index_S = str_info.find(" S ", index_S)) != std::string::npos)
    {
        list_indexes.push_back(index_S);

        index_S++;
    }
    //
    size_t index_T = 0;
    while ((index_T = str_info.find(" T ", index_T)) != std::string::npos)
    {
        list_indexes.push_back(index_T);

        index_T++;
    }
    //
    size_t index_Z = 0;
    while ((index_Z = str_info.find(" Z ", index_Z)) != std::string::npos)
    {
        list_indexes.push_back(index_Z);

        index_Z++;
    }
    //
    if (list_indexes.size() == 0)
    {
        return false;
    }

    // 逐行解析
    for (auto index : list_indexes)
    {
        //  获得第index所在的行字符串
        size_t index_tmp = str_info.find("\n", index);
        std::string str_6process_info = str_info.substr(index - 44, index_tmp - (index - 44) + 1);

        // 解析该行字符串
        TOP6ProcessInfo process_info;
        std::istringstream iss(str_6process_info);
        iss >> process_info.process_PID;
        iss >> process_info.process_USER;
        iss >> process_info.process_PR;
        iss >> process_info.process_NI;
        // read VIRT
        std::string str_tmp;
        str_tmp.clear();
        iss >> str_tmp;
        index = str_tmp.find("g", 0);

        if (index == std::string::npos) // 无字母g时
        {
            process_info.process_VIRT = atof(str_tmp.c_str());
        }
        else // 有字母g时
        {
            str_tmp = str_tmp.substr(0, str_tmp.size() - 1);
            process_info.process_VIRT = atof(str_tmp.c_str()) * 1024.0 * 1024.0;
        }
        // read RES
        str_tmp.clear();
        iss >> str_tmp;
        index = str_tmp.find("g", 0);
        if (index == std::string::npos) // 无字母g时
        {
            process_info.process_RES = atof(str_tmp.c_str());
        }
        else // 有字母g时
        {
            str_tmp = str_tmp.substr(0, str_tmp.size() - 1);
            process_info.process_RES = atof(str_tmp.c_str()) * 1024.0 * 1024.0;
        }
        // read SHR
        str_tmp.clear();
        iss >> str_tmp;
        index = str_tmp.find("g", 0);
        if (index == std::string::npos) // 无字母g时
        {
            process_info.process_SHR = atof(str_tmp.c_str());
        }
        else // 有字母g时
        {
            str_tmp = str_tmp.substr(0, str_tmp.size() - 1);
            process_info.process_SHR = atof(str_tmp.c_str()) * 1024.0 * 1024.0;
        }
        //
        iss >> process_info.process_S;
        iss >> process_info.process_percentageCPU;
        iss >> process_info.process_percentageMEM;
        iss >> process_info.process_TIMEPlus;
        iss >> process_info.process_COMMAND;

        // std::cout << process_info.process_PID << " "
        //           << process_info.process_USER << " "
        //           << process_info.process_PR << " "
        //           << process_info.process_NI << " "
        //           << process_info.process_VIRT << " "
        //           << process_info.process_RES << " "
        //           << process_info.process_SHR << " "
        //           << process_info.process_S << " "
        //           << process_info.process_percentageCPU << " "
        //           << process_info.process_percentageMEM << " "
        //           << process_info.process_TIMEPlus << " "
        //           << process_info.process_COMMAND << std::endl;

        m_list_6process_info.push_back(process_info);
    }

    return true;
}

void TOPParser::executeCMD(const char *cmd, char *result)
{
    char buf_ps[1024];
    char ps[1024] = {0};
    FILE *ptr;
    strcpy(ps, cmd);
    if ((ptr = popen(ps, "r")) != NULL)
    {
        while (fgets(buf_ps, 1024, ptr) != NULL)
        {
            strcat(result, buf_ps);
            if (strlen(result) > 10000)
                break;
        }
        pclose(ptr);
        ptr = NULL;
    }
    else
    {
        printf("popen %s error\n", ps);
    }
}

int main(int argc, char **argv)
{
    //  关于str_user_defined的制定,参考【正则表达式】即可
    // std::string str_user_defined = "sunloginc"; //[ok] 在top输出中查找包含字符串sunloginclient的行
    // std::string str_user_defined = "\\<sunloginclient\\>"; //[ok] 在top输出中精确查找包含单词sunloginclient的行
    // std::string str_user_defined = "sun|top"; //[ok] 在top输出中查找包含字符串sun或字符串top的行
    // std::string str_user_defined = "jackie.*?sun"; //[ok] 查找同时包含字符串[jackie.*?sun]的行,[.*?]表示任意多个任意字符
    std::string str_user_defined = "\\<front_end_node\\>"; //[ok] 在top输出中精确查找包含单词sunloginclient的行

    std::string top_shell_cmd = "top -n 3 -b | grep -E \"top - |Tasks:|\%Cpu|KiB Mem :|KiB Swap:|" + //与解析代码相对应,不要修改
                                str_user_defined +                                                   // 根据评估进程的不同,按格式修改
                                std::string("\"");                                                   // 不要修改

    while (1)
    {
        TOPParser reader(top_shell_cmd);
        // std::chrono::steady_clock::time_point t1 = std::chrono::steady_clock::now();
        if (reader.updateAllInfo())
        {
            auto all_process_info = reader.getAllProcessInfo();
            double sum_CPU = 0.0;
            double sum_MEM = 0.0;
            double sum_RES = 0.0;
            for (auto pi : all_process_info)
            {
                if (pi.process_USER == "jackie")
                {
                    sum_CPU += pi.process_percentageCPU;
                    sum_MEM += pi.process_percentageMEM;
                    sum_RES += pi.process_RES;
                }
            }

            auto header = reader.getHeaderInfo();
            std::cout << "system time:" << header.system_time_hh << ":" << header.system_time_mm << ":" << header.system_time_ss
                      << " \tCPU:" << sum_CPU
                      << "% \tMEM:" << sum_MEM
                      << "% \tRES:" << sum_RES / 1024.0 << "MB" << std::endl;
        }

        // std::chrono::steady_clock::time_point t2 = std::chrono::steady_clock::now();
        // std::chrono::duration<double> time_used = std::chrono::duration_cast<std::chrono::duration<double>>(t2 - t1);
        // std::cout << "time used(s):" << time_used.count() << std::endl;
    }

    return 0;
}

测试部分:ok

jackie@jackie-lenovo:~/WS_Source/learn_cpp/05-cpu_usage/build$ ./main
system time:16:1:12     CPU:26.2%       MEM:1.7%        RES:270.555MB
system time:16:1:18     CPU:25.9%       MEM:1.7%        RES:270.469MB
system time:16:1:25     CPU:25.2%       MEM:1.7%        RES:270.414MB
system time:16:1:31     CPU:20.9%       MEM:1.9%        RES:307.707MB
system time:16:1:37     CPU:19.9%       MEM:1.9%        RES:307.309MB
system time:16:1:43     CPU:22.3%       MEM:1.7%        RES:270.316MB
system time:16:1:49     CPU:21.6%       MEM:1.7%        RES:270.496MB
system time:16:1:56     CPU:19.6%       MEM:1.7%        RES:270.672MB
system time:16:2:2      CPU:19.6%       MEM:1.7%        RES:270.766MB
...
以上为C++解析输出结果(更新周期约为6.2s)

jackie@jackie-lenovo:~$ top -b  | grep -E "front"
10057 jackie    20   0  837688 276868  33956 S  19.3  1.7   6:07.08 front_end_node
10057 jackie    20   0  853372 276988  33956 S  25.9  1.7   6:07.86 front_end_node
10057 jackie    20   0  853512 277076  33956 S  19.9  1.7   6:08.46 front_end_node
10057 jackie    20   0  861512 277168  33956 S  19.6  1.7   6:09.05 front_end_node
10057 jackie    20   0  861628 277220  33956 S  15.6  1.7   6:09.52 front_end_node
10057 jackie    20   0  834268 277264  33956 S  19.7  1.7   6:10.11 front_end_node
...
以上为shell命令输出结果(更新周期默认约为3s)

使用说明

  • 第一步:通过top查看想要评估效率的程序的命令和其他特点;
  • 第二步:书写适当的正则表达式;
  • 第三步:修改源代码,包括shell命令、适当打数据处理、输出到的目标文件等;
  • 注意事项:程序更新周期约为6.2秒,它仅作为单独的程序性能评估软件使用,请勿将其写入到你的任务程序当中。

参考资料

  1. C/C++ 程序中调用命令行命令并获取命令行输出结果【我的程序的核心代码,非常感谢这位博主】
  2. grep 命令系列:grep 中的正则表达式【正则表达式这部分还是比较通用的】
  3. C++获取对应进程的cpu和内存使用情况(支持linux和windows)【当代码中周期改为3s时,结果于top近似,但需手动指定PID,使用起来不太方便】
  4. rqt_top【专门面向ROS节点的性能检测软件】

标签:20,0.0,top,jackie,内存,str,Linux,CPU
From: https://www.cnblogs.com/jackie2455/p/16769389.html

相关文章