文件解释
在实际工作中有时需要程序打印出某个进程的内存占用情况以作参考, 下面介绍一种通过Linux
下的伪文件系统/proc
计算某进程内存占用的程序实现方法.
首先, 为什么会有所谓的 伪文件 呢. Linux
系统的文件类型大致可分为三类: 普通文件, 目录文件和伪文件. 伪文件不是用来存储数据的, 因此这些文件不占用磁盘空间, 只是存在于内存中. /proc
让你可以与内核内部数据进行交互, 获取有关进程的有用信息.
下面主要介绍一下 /proc
下面的四个文件:
/proc/stat, /proc/meminfo, /proc/<pid>/stat, /proc/<pid>/status.
以及/sys/devices/virtual/thermal/thermal_zone*/
下的文件
/proc/stat
存放系统的cpu
时间, 该文件包含了所有cpu
活动的信息.
cpu 72389 2891 16811 1148664 31374 0 67 0 0 0
cpu0 17608 452 3786 288899 6210 0 30 0 0 0
cpu1 18724 926 4598 285844 8911 0 15 0 0 0
cpu2 16803 658 3726 288710 7220 0 7 0 0 0
cpu3 19254 855 4700 285209 9032 0 13 0 0 0
...
...
...
/proc/meminfo
存放系统的内存信息, 通过文件中各个变量的名字便可知其代表的信息.
MemTotal: 4046236 kB
MemFree: 1054440 kB
MemAvailable: 2460060 kB
Buffers: 359688 kB
Cached: 1158056 kB
SwapCached: 0 kB
Active: 2020096 kB
Inactive: 677948 kB
Active(anon): 1181376 kB
...
...
...
/proc/<pid>/stat
存放某个进程的cpu信息
2476 (firefox) S 1773 1910 1910 0 -1 4210688 3413511 1712 757 1 45466 4629 2 7 20 0 57 0 20381 1774743552 150565 18446744073709551615 94844693012480 94844693126372 140732961864784 140732961858304 139747170914269 0 0 4096 33572079 0 0 0 17 2 0 0 1178 0 0 94844695226592 94844695228536 94844713955328 140732961867643 140732961867668 140732961867668 140732961869791 0
/proc/<pid>/status
存放某个进程的cpu信息以及一些综合信息
Name: firefox
State: S (sleeping)
Tgid: 2476
Ngid: 0
Pid: 2476
PPid: 1773
TracerPid: 0
Uid: 1000 1000 1000 1000
Gid: 1000 1000 1000 1000
FDSize: 256
Groups: 4 24 27 30 46 108 124 1000
NStgid: 2476
NSpid: 2476
NSpgid: 1910
NSsid: 1910
VmPeak: 1722812 kB
VmSize: 1690920 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 684048 kB
VmRSS: 600324 kB
VmData: 993040 kB
VmStk: 192 kB
...
...
...
以上数据都可以通过文件读取的方式来获取. 根据自己实验的需要可以计算相应的数据, 比如pmem = VmRSS/MemTotal*100
等等.
/sys/devices/virtual/thermal/thermal_zone*/type
文件:记录的是温度类型, 查看硬件
/sys/devices/virtual/thermal/thermal_zone*/temp
查看温度,以下数字分别对应以上硬件,将数字除以1000得出实际温度(摄氏度)
C/C++代码获取
get_status.h
//
// Created by adu on 6/14/20.
//
#ifndef MAVKIT_MAVHX_TX2_GET_STATUS_H
#define MAVKIT_MAVHX_TX2_GET_STATUS_H
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <thread>
#include <mavhx/mavhx_msg_tx2_status.h>
#include <mavkit/MavlinkLogWriter.h>
#define VMRSS_LINE 17 // 随着不同系统改变,应用之前查看文件确认行数
#define VMSIZE_LINE 13 // 随着不同系统改变,应用之前查看文件确认行数
#define PROCESS_ITEM 14
typedef struct {
unsigned long user;
unsigned long nice;
unsigned long system;
unsigned long idle;
}Total_Cpu_Occupy_t;
typedef struct {
unsigned int pid;
unsigned long utime; //user time
unsigned long stime; //kernel time
unsigned long cutime; //all user time
unsigned long cstime; //all dead time
}Proc_Cpu_Occupy_t;
class MavlinkLogWriter;
class Tx2GetStatus{
public:
Tx2GetStatus();
~Tx2GetStatus();
void start();
void join();
void run();
void SetLogWriter(MavlinkLogWriter * pLogWriter);
// 得到用户名称
void GetUserName(std::string userName);
//得到进程名字
void GetProcessName(std::string processName);
//获取第N项开始的指针
const char* get_items(const char*buffer ,unsigned int item);
//获取总的CPU时间
unsigned long get_cpu_total_occupy();
//获取进程的CPU时间
unsigned long get_cpu_proc_occupy(unsigned int pid);
//获取CPU占用率
float get_proc_cpu(unsigned int pid);
//获取进程占用内存
unsigned int get_proc_mem(unsigned int pid);
//获取进程占用虚拟内存
unsigned int get_proc_virtualmem(unsigned int pid);
//进程本身
int get_pid(const char* process_name, const char* user = nullptr);
// 获得CPU温度
int get_cpu_temp();
private:
std::string msProcessName;
std::string msUserName;
MavlinkLogWriter* mpLogWriter;
std::thread *starting_thread;
};
#endif //MAVKIT_MAVHX_TX2_GET_STATUS_H
get_status.cpp
//
// Created by adu on 6/14/20.
//
#include <mavhx/mavhx_tx2_get_status.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
#include <string.h>
#include <stdlib.h>
#include <string>
#include <iostream>
#define VMRSS_LINE 17
#define VMSIZE_LINE 13
#define PROCESS_ITEM 14
Tx2GetStatus::Tx2GetStatus() : mpLogWriter(NULL), starting_thread(NULL) {}
Tx2GetStatus::~Tx2GetStatus() {}
void Tx2GetStatus::start() {
if(starting_thread == NULL) {
starting_thread = new std::thread(&Tx2GetStatus::run, this);
}
}
void Tx2GetStatus::join() {
starting_thread->join();
}
void Tx2GetStatus::run() {
mavlink_message_r SMsgTx2Status;
mavlink_tx2_status_t STx2Status;
if(msProcessName.empty()){
throw std::logic_error("Process Name is NULL.");
}
int32_t pid = get_pid(msProcessName.c_str(), msUserName.c_str());
std::cout << "process id " << pid << std::endl;
STx2Status.pid = pid;
while (true) {
STx2Status.temp = get_cpu_temp();
STx2Status.pcpu = get_proc_cpu(pid);
STx2Status.pmem = get_proc_mem(pid);
STx2Status.vmem = get_proc_virtualmem(pid);
mavlink_msg_tx2_status_encode(&SMsgTx2Status, &STx2Status);
if( mpLogWriter != NULL) {
mpLogWriter->send_message(SMsgTx2Status);
}
sleep(2);
}
}
void Tx2GetStatus::SetLogWriter(MavlinkLogWriter * pLogWriter){
mpLogWriter = pLogWriter;
}
void Tx2GetStatus::GetUserName(std::string userName){
msUserName = userName;
}
//得到进程名字
void Tx2GetStatus::GetProcessName( std::string processName) {
msProcessName = processName;
}
//获取第N项开始的指针
const char* Tx2GetStatus::get_items(const char*buffer ,unsigned int item){
const char *p =buffer;
int len = strlen(buffer);
int count = 0;
for (int i=0; i<len;i++){
if (' ' == *p){
count ++;
if(count == item -1){
p++;
break;
}
}
p++;
}
return p;
}
//获取总的CPU时间
unsigned long Tx2GetStatus::get_cpu_total_occupy(){
FILE *fd;
char buff[1024]={0};
Total_Cpu_Occupy_t t;
fd =fopen("/proc/stat","r");
if (nullptr == fd){
return 0;
}
fgets(buff,sizeof(buff),fd);
char name[64]={0};
sscanf(buff,"%s %ld %ld %ld %ld",name,&t.user,&t.nice,&t.system,&t.idle);
fclose(fd);
return (t.user + t.nice + t.system + t.idle);
}
//获取进程的CPU时间
unsigned long Tx2GetStatus::get_cpu_proc_occupy(unsigned int pid){
char file_name[64]={0};
Proc_Cpu_Occupy_t t;
FILE *fd;
char line_buff[1024]={0};
sprintf(file_name,"/proc/%d/stat",pid);
fd = fopen(file_name,"r");
if(nullptr == fd){
return 0;
}
fgets(line_buff,sizeof(line_buff),fd);
sscanf(line_buff,"%u",&t.pid);
const char *q =get_items(line_buff,PROCESS_ITEM);
sscanf(q,"%ld %ld %ld %ld",&t.utime,&t.stime,&t.cutime,&t.cstime);
fclose(fd);
return (t.utime + t.stime + t.cutime + t.cstime);
}
//获取CPU占用率
float Tx2GetStatus::get_proc_cpu(unsigned int pid){
unsigned long totalcputime1,totalcputime2;
unsigned long procputime1,procputime2;
totalcputime1=get_cpu_total_occupy();
procputime1=get_cpu_proc_occupy(pid);
usleep(500000);
totalcputime2=get_cpu_total_occupy();
procputime2=get_cpu_proc_occupy(pid);
float pcpu = 0.0;
if(0 != totalcputime2-totalcputime1){
pcpu=100.0 * (procputime2-procputime1)/(totalcputime2-totalcputime1);
}
return pcpu;
}
//获取进程占用内存
unsigned int Tx2GetStatus::get_proc_mem(unsigned int pid){
char file_name[64]={0};
FILE *fd;
char line_buff[512]={0};
sprintf(file_name,"/proc/%d/status",pid);
fd =fopen(file_name,"r");
if(nullptr == fd){
return 0;
}
char name[64];
int vmrss;
//获取vmrss:实际物理内存占用
//读取VmRSS这一行的数据
for (int i=0; i<VMRSS_LINE-1;i++){
fgets(line_buff,sizeof(line_buff),fd);
}
fgets(line_buff,sizeof(line_buff),fd);
sscanf(line_buff,"%s %d",name,&vmrss);
fclose(fd);
return vmrss;
}
//获取进程占用虚拟内存
unsigned int Tx2GetStatus::get_proc_virtualmem(unsigned int pid){
char file_name[64]={0};
FILE *fd;
char line_buff[512]={0};
sprintf(file_name,"/proc/%d/status",pid);
fd =fopen(file_name,"r");
if(nullptr == fd){
return 0;
}
char name[64];
int vmsize;
for (int i=0; i<VMSIZE_LINE-1;i++){
fgets(line_buff,sizeof(line_buff),fd);
}
fgets(line_buff,sizeof(line_buff),fd);
sscanf(line_buff,"%s %d",name,&vmsize);
fclose(fd);
return vmsize;
}
//进程本身
int Tx2GetStatus::get_pid(const char* process_name, const char* user)
{
if(user == nullptr){
user = getlogin();
}
char cmd[512];
if (user){
sprintf(cmd, "pgrep %s -u %s", process_name, user);
}
FILE *pstr = popen(cmd,"r");
if(pstr == nullptr){
return 0;
}
char buff[512];
::memset(buff, 0, sizeof(buff));
if(NULL == fgets(buff, 512, pstr)){
return 0;
}
return atoi(buff);
}
// 获得CPU温度
int Tx2GetStatus::get_cpu_temp()
{
FILE *fd;
int temp;
char buff[256];
fd = fopen("/sys/devices/virtual/thermal/thermal_zone0/temp","r");
fgets(buff,sizeof(buff),fd);
sscanf(buff, "%d", &temp);
fclose(fd);
return temp/1000;
}
参考链接:
https://www.cnblogs.com/bozhicheng/p/6216667.html
http://blog.sina.com.cn/s/blog_49efd54001019r1j.html
https://blog.csdn.net/chenjambo/article/details/80945992