生活随笔
收集整理的這篇文章主要介紹了
linux监测指定进程的CPU及物理内存消耗情况(c程序)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
近日,由于工作要求,研究了一下如何在linux系統下對某個指定的單個進程進行監測,分析其CPU及物理內存的使用情況,并基于c語言寫了一個獨立的模塊,完整的實現上述功能。現將整個模塊的代碼貼上,以便日后借鑒,并與同道中人分享。源碼在ubuntu 16.04、嵌入式主板等多個系統下運行親測正常,各類注釋都比較齊全,對模塊的使用方法也有介紹,此處就不再贅述,若有問題,自行閱讀源碼即可。
注:另有一份代碼是基于bash腳本的,同樣實現上述的功能,貼于另一篇博客,如有需要,可點擊此處跳轉。
#include <time.h>
#include <ctype.h>
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <printf.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <dirent.h>
#include <sys/time.h>
#include <sys/types.h>
#define CPU_START_POS 14
#define READ_BUF_SIZE 512 #define LOG_ENABLE "logon" #define MONITR_DATA_PATH "monitor_log"
#define MONITR_DATA_BEXT ".log"
static long s_cur_pro_cpu
, s_pre_pro_cpu
;
static long s_cur_sys_cpu
, s_pre_sys_cpu
; static int s_needlogfile
;
static char s_recfilepath
[128];
static int excute_cmd(char *comand
)
{int status
;status
= system(comand
);if (status
== -1) { return -1;}if (WIFEXITED(status
) == 0) { return -1;}if (WEXITSTATUS(status
) != 0) { return -1;}return 1;
}
static int target_is_exist(char *target_path
)
{int result
;result
= access(target_path
, F_OK
);return result
;
}
static int make_sudir(char *fpath
)
{char *comand
;int pathlen
, result
;if (target_is_exist(fpath
) == 1) { return 0;}pathlen
= strlen(fpath
) + 16; comand
= (char *)malloc(pathlen
);assert(comand
!= NULL);memset(comand
, 0, pathlen
);sprintf(comand
, "mkdir -p %s", fpath
);result
= excute_cmd(comand
);free(comand
); return result
;
}
static void write_recfile(char *log_path
, char *log_text
)
{FILE
*log_hdl
;log_hdl
= fopen(log_path
, "a");assert(log_hdl
!= NULL); assert(fseek(log_hdl
, 0, SEEK_END) == 0); assert(fwrite(log_text
, strlen(log_text
), 1, log_hdl
) == 1); assert(fclose(log_hdl
) == 0);
}
static void generate_rfile_path(char *target
)
{struct timeval tv
;struct tm tm
;char timestr
[32];memset(timestr
, 0, sizeof(timestr
));gettimeofday(&tv
, NULL);tm
= *localtime(&tv
.tv_sec
);sprintf(timestr
, "%.4d%.2d%.2d_%.2d%.2d%.2d", tm
.tm_year
+ 1900, tm
.tm_mon
+ 1, tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
);assert(make_sudir(MONITR_DATA_PATH
) != -1);memset(s_recfilepath
, 0, sizeof(s_recfilepath
));sprintf(s_recfilepath
, "%s/%s_%s%s", MONITR_DATA_PATH
, target
, timestr
, MONITR_DATA_BEXT
);printf("log is enabled. log_file \"%s\"\n", s_recfilepath
);
}
static void record_loginfo(char *info
)
{struct timeval tv
;struct tm tm
;int tlen
;char *wstr
;tlen
= strlen(info
) + 32; wstr
= malloc(tlen
);assert(wstr
!= 0);gettimeofday(&tv
, NULL);tm
= *localtime(&tv
.tv_sec
);sprintf(wstr
, "[%04d/%02d/%02d %02d:%02d:%02d] %s", tm
.tm_year
+ 1900, tm
.tm_mon
+ 1, tm
.tm_mday
, tm
.tm_hour
, tm
.tm_min
, tm
.tm_sec
, info
);printf("%s", wstr
); if (s_needlogfile
> 0) {write_recfile(s_recfilepath
, wstr
); }
}
int find_pid_by_name(char* pidName
)
{DIR
*prodir
;FILE
*status
;struct dirent
*next
;char finame
[READ_BUF_SIZE
];char tmpbuf
[READ_BUF_SIZE
];char pcname
[READ_BUF_SIZE
];prodir
= opendir("/proc"); assert(prodir
!= NULL);while ((next
= readdir(prodir
)) != NULL) { if (strcmp(next
->d_name
, "..") == 0) {continue;}if (!isdigit(*next
->d_name
)) { continue;}sprintf(finame
, "/proc/%s/status", next
->d_name
); if (!(status
= fopen(finame
, "r"))) {continue;}if (fgets(tmpbuf
, READ_BUF_SIZE
- 1, status
) == NULL) { fclose(status
);continue;}fclose(status
);sscanf(tmpbuf
, "%*s %s", pcname
); if (strcmp(pcname
, pidName
) == 0) { return strtol(next
->d_name
, NULL, 0);}}return 0;
}
char *get_items_by_pos(char *buff
, unsigned int numb
)
{char *crpos
;int i
, ttlen
, count
;crpos
= buff
;ttlen
= strlen(buff
);count
= 0;for (i
= 0; i
< ttlen
; i
++) {if (' ' == *crpos
) { count
++;if (count
== (numb
- 1)) { crpos
++;break;}}crpos
++;}return crpos
;
}
long get_pro_cpu_time(unsigned int pid
)
{FILE
*fd
;char *vpos
, buff
[1024];long utime
, stime
, cutime
, cstime
;sprintf(buff
, "/proc/%d/stat", pid
); fd
= fopen(buff
, "r");assert(fd
!= NULL);assert(fgets(buff
, sizeof(buff
), fd
) != NULL); vpos
= get_items_by_pos(buff
, CPU_START_POS
); sscanf(vpos
, "%ld %ld %ld %ld", &utime
, &stime
, &cutime
, &cstime
); fclose(fd
);return (utime
+ stime
+ cutime
+ cstime
);
}
long get_sys_cpu_time(void)
{FILE
*fd
;char name
[32], buff
[1024];long user
, nice
, syst
, idle
;fd
= fopen("/proc/stat", "r"); assert(fd
!= NULL);assert(fgets(buff
, sizeof(buff
), fd
) != NULL); sscanf(buff
, "%s %ld %ld %ld %ld", name
, &user
, &nice
, &syst
, &idle
); fclose(fd
);return (user
+ nice
+ syst
+ idle
);
}
float get_cpu_stat(unsigned int pid
)
{float ratio
;s_cur_pro_cpu
= get_pro_cpu_time(pid
);s_cur_sys_cpu
= get_sys_cpu_time();if ((s_cur_pro_cpu
== s_pre_pro_cpu
) || (s_cur_sys_cpu
== s_pre_sys_cpu
) || (s_cur_pro_cpu
== 0) || (s_cur_sys_cpu
== 0)) {ratio
= 0;} else {ratio
= (100.0 * (s_cur_pro_cpu
- s_pre_pro_cpu
)) / (s_cur_sys_cpu
- s_pre_sys_cpu
);}s_pre_pro_cpu
= s_cur_pro_cpu
;s_pre_sys_cpu
= s_cur_sys_cpu
;return ratio
;
}
unsigned int get_mem_stat(unsigned int pid
)
{FILE
*fd
;int vmrss
;char *valid
, sbuff
[32], tbuff
[1024];sprintf(tbuff
, "/proc/%d/status", pid
); fd
= fopen(tbuff
, "r");assert(fd
!= NULL);while (1) { assert(fgets(tbuff
, sizeof(tbuff
), fd
) != NULL); valid
= strstr(tbuff
, "VmRSS"); if (valid
!= NULL) { break;}}sscanf(tbuff
, "%s %d", sbuff
, &vmrss
); fclose(fd
);return vmrss
;
}
int main(int argc
, char *argv
[])
{unsigned int pid
, rtime
;char *name_pos
, *proc_name
, sstr
[128];if (argc
< 3) {printf("invalid cmd!!! should specify \"proc_name\" and \"refresh_time\"\n");return 1;}proc_name
= argv
[0]; name_pos
= strrchr(proc_name
, '/');if (NULL != name_pos
){ proc_name
= name_pos
+ 1;}printf("proc \"%s\" starting...\n", proc_name
);rtime
= atoi(argv
[2]); if ((rtime
== 0) || (rtime
> 60)) {printf("invalid refresh_time(%d)!!! valid range: 0-60\n", rtime
);return 1;}s_needlogfile
= 0; if ((argc
== 4) && (strcmp(argv
[3], LOG_ENABLE
) == 0)) { generate_rfile_path(argv
[1]); s_needlogfile
= 1;}while (1) {pid
= find_pid_by_name(argv
[1]);if (pid
== 0) {sprintf(sstr
, "proc \"%s\" not found...\n", argv
[1]);} else {sprintf(sstr
, "cpu %.2f%%, mem %d KB\n", get_cpu_stat(pid
), get_mem_stat(pid
));}record_loginfo(sstr
);sleep(rtime
);}return 0;
}
總結
以上是生活随笔為你收集整理的linux监测指定进程的CPU及物理内存消耗情况(c程序)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。