[Linux C/C++]系统CPU、内存、网络资源占用率监控

任务目标

在基于Linux系统的主机上,对主机运行状态进行监控,衡量终端负载情况。相当于简单的系统资源管理器功能。该设计目标是实现对:
(1)CPU占用率
(2)系统运行时长
(3)内存占用率
(4)网络接口属性
(5)网卡速率信息

的监控。

CPU占用率

我们通过读取/proc/stat文件获取当前系统的CPU占用率。

/proc文件系统

proc是一个只存在内存当中的伪文件系统。它以文件系统的方式为内核与进程提供通信的接口。用户和应用程序可以通过/proc得到动态的从系统内核读出的系统的信息,并可以改变内核的某些参数。

/proc/stat

/proc/stat 包含了系统启动以来的许多关于kernel和系统的统计信息, 其中包括CPU运行情况、中断统计、启动时间、上下文切换次数、运行中的进程等等信息。其实,/proc/stat反映的就是CPU总的占用时间,如下图所示。
[CPU指标]:user,nice, system, idle, iowait, irq, softirq
第一行内容表示总的CPU信息,如果主机有多核,会有多个CPU0~n;
Alt

CPU利用率的计算

CPU利用率分为用户态,系统态和空闲态,分别表示CPU处于用户态执行的时间,系统内核执行的时间,和空闲系统进程执行的时间。平时所说的CPU利用率是指:CPU执行非系统空闲进程的时间 / CPU总的执行时间。
1.定义CPU信息结构体,用于存储各模式下的CPU使用时间。

typedef struct _CPU_PACKED
{
  char name[16];
  unsigned int user;   //用户模式
  unsigned int nice;   //低优先级的用户模式
  unsigned int system; //内核模式
  unsigned int idle;   //空闲处理器时间
} CPU_OCCUPY;

2.打开/proc/stat文件,利用sscanf函数读取需要的数据。

  fd = fopen("/proc/stat", "r");
  if (fd == NULL) {
      perror("open /proc/stat failed\n");
      exit(0);
  }
  fgets(buff, sizeof(buff), fd);
  sscanf(buff, "%s %u %u %u %u", cpu->name, &cpu->user, &cpu->nice, &cpu->system, &cpu->idle);
  fclose(fd);

计算方法:

  1. t1: 第一次采集(用户+优先级+系统+空闲)的时间
  2. 过一段时间,ex:sleep(1);
  3. t2:第二次(用户+优先级+系统+空闲)的时间
  4. user :用户模式第一次和第二次的时间之差
  5. system:系统第一次和第二次的时间之差
    在这里插入图片描述

内存、运行时长

Linux中,sysinfo是用来获取系统相关信息的结构体。
具体定义如下:
在这里插入图片描述
通过sysinfo函数获取上述结构体信息。

    int ret = 0;
    ret = sysinfo(&info);
    if (ret != 0) {
        perror("get sys_info failed\n");
        exit(0);
    }

定义主机状态信息结构体(如下),以保存主机的时长、使用率信息。

/*主机的状态信息结构体*/
typedef struct _HOST_STATE{
    int hour;
    int minute;
    double cpu_used;
    double mem_used ;
}HOST_STATE;

系统运行时间

通过uptime参数获取
在这里插入图片描述
在这里插入图片描述

内存利用率

通过totalram、freeram参数获取
在这里插入图片描述

网络接口属性

ifreq、ifconf结构体

ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。其中包含了一个接口的名字和具体内容——(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。
ifreq包含在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。
在这里插入图片描述
网卡接口名称、MAC地址、IP地址就保存于以下字段中。通过ifconf结构体我们可以获取到本机当前所有活动网卡的相关属性。
在这里插入图片描述

/proc/net/dev

/proc/net/dev文件就是提供给用户读取或更改网络适配器及统计信息的途径

  1. interface:接口的名字
  2. Receive:表示收包
  3. Transmit:表示收包
  4. bytes:表示收发的字节数

在这里插入图片描述
为了存储网卡相关信息,定义如下结构体。
同时采用链表结构动态存储网卡统计信息,以实现获取本机上的所有网卡设备。

/*网卡设备信息结构体*/
typedef struct _NET_INTERFACE
{
  char name[16];  /*网络接口名称*/
  char ip[16];    /*网口IP*/
  double d_speed; /*下行速度*/
  double u_speed; /*上行速度*/
  char mac[13];   /*网口MAC地址*/
  /*上下行速度级别 bit 7~0
  *bit[0]=d_speed  
  *bit[1]=u_speed 
  *1:MB/s 0:KB/s
  */
  unsigned char speed_level;   /**/
  struct _NET_INTERFACE *next; /*链表指针*/
} NET_INTERFACE;

网速计算

定义RTX_BYTES结构体用于存储网卡特定时刻的收发包情况。

/*收发数据包结构体*/
typedef struct _RTX_BYTES
{
  long int tx_bytes;
  long int rx_bytes;
  struct timeval rtx_time;
} RTX_BYTES;

通过打开/proc/net/dev文件,按行读取可获得各网卡当前时刻总的收发包信息。程序示例如下。

    open_netconf(&net_dev_file);
    //获取时间
    gettimeofday(&rtx->rtx_time, NULL);
    //从第三行开始读取网络接口数据
    while ((read = getline(&line, &bytes_read, net_dev_file)) != -1) {
        if ((++i) <= 2)
            continue;
        if (strstr(line, name) != NULL) {
            memset(str1, 0x0, 32);
            memset(str2, 0x0, 32);
            sscanf(line, "%*s%s%*s%*s%*s%*s%*s%*s%*s%s", str1, str2);
            rtx->tx_bytes = atol(str2);
            rtx->rx_bytes = atol(str1);
#if DEBUG
            printf("name:%8s\t tx:%10ld\trx:%10ld\n", name, rtx->tx_bytes, rtx->rx_bytes);
#endif
        }
    }
    fclose(net_dev_file);

网速的计算同CPU利用率计算一样,都需要通过两次采集,统计特定时间间隔内的信息来计算。
计算方法:

  1. t1: 当前时刻收发包字节数bytes1
  2. 过一段时间,ex:sleep(1);
  3. t2:当前时间收发包字节数bytes2
    在这里插入图片描述
    程序示例:首先回去两次采集的间隔时长,再通过收发包字节数计算上下行网速。
 long int time_lapse;

    time_lapse = (rtx1->rtx_time.tv_sec * 1000 + rtx1->rtx_time.tv_usec / 1000) - (rtx0->rtx_time.tv_sec * 1000 + rtx0->rtx_time.tv_usec / 1000);

    *d_speed = (rtx1->rx_bytes - rtx0->rx_bytes) * 1.0 / (1024 * time_lapse * 1.0 / 1000);
    *u_speed = (rtx1->tx_bytes - rtx0->tx_bytes) * 1.0 / (1024 * time_lapse * 1.0 / 1000);

程序流程

项目中共设计两个线程分别采集网速信息、CPU&内存&运行时长信息。整体流程如下。
在这里插入图片描述
main函数展示:

    int nums = 0;
    //网卡结构体指针初始化
    p_interface = (NET_INTERFACE *)malloc(sizeof(NET_INTERFACE));
    //获取本机网卡数量
    get_interface_info(&p_interface, &nums);
    printf("net_interface nums: %d\n", nums);

    show_netinterfaces(p_interface, 0);
    //创建两个线程
    pthread_t thread_net_id, thread_core_id;
    //线程1:网络信息监控线程
    pthread_create(&thread_net_id, NULL, (void *)thread_net, NULL);
    //线程2:CPU、内存信息监控
    pthread_create(&thread_core_id, NULL, (void *)thread_core, NULL);

结果展示

终端可持续实时输出CPU、内存、运行时间,网卡IP、MAC、上下行速率信息。
再与本机的监控软件信息对比,证明输出结果可信。
程序输出结果
监控软件显示的CPU、内存使用信息:
CPU&内存信息
输出本机网卡信息:
本机网卡信息

完整的项目地址

github

https://github.com/ctguLMY/linux_terminal_monitor

gitee

https://gitee.com/mying666/linux_terminal_monitor

  • 7
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
可以使用C/C++通过读取/proc/stat文件来获取Linux系统CPU用率。具体实现可以参考以下代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAX_LINE_LENGTH 100 int main() { FILE *fp; char line[MAX_LINE_LENGTH]; char *token; unsigned long long user, nice, system, idle, iowait, irq, softirq, steal, guest, guest_nice; while (1) { fp = fopen("/proc/stat", "r"); fgets(line, MAX_LINE_LENGTH, fp); fclose(fp); if (strncmp(line, "cpu ", 4) == 0) { token = strtok(line, " "); token = strtok(NULL, " "); user = strtoull(token, NULL, 10); token = strtok(NULL, " "); nice = strtoull(token, NULL, 10); token = strtok(NULL, " "); system = strtoull(token, NULL, 10); token = strtok(NULL, " "); idle = strtoull(token, NULL, 10); token = strtok(NULL, " "); iowait = strtoull(token, NULL, 10); token = strtok(NULL, " "); irq = strtoull(token, NULL, 10); token = strtok(NULL, " "); softirq = strtoull(token, NULL, 10); token = strtok(NULL, " "); steal = strtoull(token, NULL, 10); token = strtok(NULL, " "); guest = strtoull(token, NULL, 10); token = strtok(NULL, " "); guest_nice = strtoull(token, NULL, 10); unsigned long long total = user + nice + system + idle + iowait + irq + softirq + steal; unsigned long long idle_time = idle + iowait; float usage = 100.0 * (total - idle_time) / total; printf("CPU usage: %.2f%%\n", usage); } } return 0; } ``` 该程序在一个无限循环中,每次读取/proc/stat文件中的第一行,提取出CPU的各项计数器,计算出CPU用率,并输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我楚狂声

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值