235 lines
7.9 KiB
C
235 lines
7.9 KiB
C
//
|
||
// Created by Iain on 2021/7/17.
|
||
//
|
||
|
||
#include "ProcessInfo.h"
|
||
#include <unistd.h>
|
||
#include <stdio.h>
|
||
#include <dirent.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
|
||
#define LOG
|
||
#define BUFFER_SIZE_PROC_STAT 1024
|
||
#define BUFFER_SIZE_PROC_STATUS 128
|
||
#define STAT_UTIME 13
|
||
#define STAT_STIME 14
|
||
#define STAT_VSZ 22
|
||
#define STAT_RSS 23
|
||
|
||
extern Proc_Info Proc_List[LIMIT_PROCESS_NUMBER];
|
||
|
||
inline void freeProcInfo(Proc_Info *proc) {
|
||
int i;
|
||
proc->pid = 0;
|
||
proc->point = 0;
|
||
strcpy(proc->name, "");
|
||
for (i = 0; i < UPDATE_FREQUENCY; i++) {
|
||
proc->cpuInfo[i].utime = 0;
|
||
proc->cpuInfo[i].stime = 0;
|
||
proc->memInfo[i].vsz = 0;
|
||
proc->memInfo[i].vsz = 0;
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
void freeProcInfoList() {
|
||
int i;
|
||
for (i = 0; i < LIMIT_PROCESS_NUMBER; i++) {
|
||
freeProcInfo(&Proc_List[i]);
|
||
}
|
||
return;
|
||
}
|
||
|
||
int foundProcNode(unsigned int pid) {
|
||
int i;
|
||
for (i = 0; i < LIMIT_PROCESS_NUMBER; i++) {
|
||
if ((Proc_List + i)->pid == pid) {
|
||
return i;
|
||
}
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
int foundFreeProcNode() {
|
||
int i;
|
||
i = foundProcNode(0);
|
||
if (i == -1) {
|
||
perror("No free procInfo node in procList");
|
||
}
|
||
return i;
|
||
}
|
||
|
||
int setFreeProcNode(unsigned int pid) {
|
||
//found PID name
|
||
char buf[BUFFER_SIZE_PROC_STATUS] = {0};
|
||
char PID_name[LIMIT_PROCESS_Name_Length] = {0};
|
||
char file_path[64] = {0};
|
||
sprintf(file_path, "/proc/%d/status", pid);
|
||
FILE *fp;
|
||
if ((fp = fopen(file_path, "r")) == NULL) {
|
||
perror("fail to read /proc/PID/status");
|
||
return -1;
|
||
}
|
||
fgets(buf, BUFFER_SIZE_PROC_STATUS, fp);
|
||
#if defined(LOG)
|
||
printf("/proc/%d/status: %s", pid, buf);
|
||
#endif
|
||
sscanf(buf, "Name: %s", PID_name);
|
||
|
||
//compare PID name with whitelist
|
||
|
||
//check PID in ProcList
|
||
if (foundProcNode(pid) == -1) {
|
||
return -1;
|
||
}
|
||
|
||
//found free Proc Node
|
||
int i = foundFreeProcNode();
|
||
|
||
//set Proc Info
|
||
Proc_List[i].pid = pid;
|
||
strcpy(Proc_List[i].name, PID_name);
|
||
}
|
||
|
||
//unsigned int *getProcess() {
|
||
// DIR *dir;
|
||
// struct dirent *entry;
|
||
// unsigned int id = 0;
|
||
// static unsigned int ids[LIMIT_PROCESS_NUMBER] = {0};
|
||
//
|
||
// if ((dir = opendir("/proc/")) == NULL) {
|
||
// perror("cannot access /proc directory");
|
||
// exit(-1);
|
||
// }
|
||
//
|
||
// int index = 0;
|
||
// int i;
|
||
// unsigned int temp;
|
||
// while ((direntp = readdir(dirp)) != NULL) {
|
||
// id = atoi(direntp->d_name);
|
||
// if (id > 0) {
|
||
// for (i = 0; i < index; i++) {
|
||
// if (ids[i] > id) {
|
||
// temp = id;
|
||
// id = ids[i];
|
||
// ids[i] = temp;
|
||
// }
|
||
// }
|
||
// ids[index] = id;
|
||
// index++;
|
||
// }
|
||
// }
|
||
// closedir(dirp);
|
||
// return &ids[0];
|
||
//}
|
||
|
||
//update process cpu time and mem info by /proc/PID/stat
|
||
//example: 1 (systemd) S 0 1 1 0 -1 4194560 16465 675919 50 519 44 100 678 258 20 0 1 0 13 44421120 1253 18446744073709551615 94869015482368 94869016924823 140724538057904 0 0 0 671173123 4096 1260 1 0 0 17 0 0 0 14 0 0 94869019025816 94869019170360 94869036843008 140724538064796 140724538064863 140724538064863 140724538064863 0
|
||
/* pid 进程ID 0
|
||
* comm task_struct结构体的进程名
|
||
* state 进程状态, 此处为S
|
||
* ppid 父进程ID (父进程是指通过fork方式,通过clone并非父进程)
|
||
* pgrp 进程组ID
|
||
* session 进程会话组ID
|
||
* tty_nr 当前进程的tty终点设备号
|
||
* tpgid 控制进程终端的前台进程号
|
||
* flags 进程标识位,定义在include/linux/sched.h中的PF
|
||
* minflt 次要缺页中断的次数,即无需从磁盘加载内存页. 比如COW和匿名页
|
||
* cminfl 当前进程等待子进程的minflt
|
||
* majflt 主要缺页中断的次数,需要从磁盘加载内存页. 比如map文件
|
||
* majflt 当前进程等待子进程的majflt
|
||
* utime 该进程处于用户态的时间,单位jiffies 13
|
||
* stime 该进程处于内核态的时间,单位jiffies 14
|
||
* cutime 当前进程等待子进程的utime
|
||
* cstime 当前进程等待子进程的utime
|
||
* priority 进程优先级, 此次等于10.
|
||
* nice nice值,取值范围[19, -20],此处等于-10
|
||
* num_threads 线程个数, 此处等于221
|
||
* itrealvalue 该字段已废弃,恒等于0
|
||
* starttime 自系统启动后的进程创建时间,单位jiffies
|
||
* vsize 进程的虚拟内存大小,单位为bytes 22
|
||
* rss 进程独占内存,单位pages,4K 23
|
||
* rsslim rss大小上限
|
||
* start_code 该任务在虚拟地址空间的代码段的起始地址
|
||
* end_code 该任务在虚拟地址空间的代码段的结束地址。
|
||
* start_stack 该任务在虚拟地址空间的栈的结束地址。
|
||
* kstkesp esp(32 位堆栈指针) 的当前值, 与在进程的内核堆栈页得到的一致。
|
||
* kstkeip 指向将要执行的指令的指针, EIP(32 位指令指针)的当前值。
|
||
* pendingsig 待处理信号的位图,记录发送给进程的普通信号。
|
||
* block_sig 阻塞信号的位图。
|
||
* sigign 忽略的信号的位图。
|
||
* sigcatch 被俘获的信号的位图。
|
||
* wchan 如果该进程是睡眠状态,该值给出调度的调用点。
|
||
* nswap 被swapped的页数,当前没用。
|
||
* cnswap 所有子进程被swapped 的页数的和,当前没用。
|
||
* exit_signal 该进程结束时,向父进程所发送的信号。
|
||
* task_cpu 运行在哪个 CPU 上。
|
||
* task_rt_priority 实时进程的相对优先级别。
|
||
* task_policy 进程的调度策略,0=非实时进程,1=FIFO实时进程;2=RR实时进程
|
||
* blio_ticks 等待阻塞IO的时间
|
||
* gtime guest time of the task in jiffies
|
||
* cgtime guest time of the task children in jiffies
|
||
* start_data address above which program data+bss is placed
|
||
* end_data address below which program data+bss is placed
|
||
* start_brk address above which program heap can be expanded with br
|
||
*/
|
||
int updateProcInfo(Proc_Info *proc) {
|
||
char file_path[64] = {0};
|
||
char buffer[BUFFER_SIZE_PROC_STAT] = {0};
|
||
sprintf(file_path, "/proc/%d/stat", proc->pid);
|
||
FILE *fd = NULL;
|
||
fd = fopen(file_path, "r");
|
||
if (fd == NULL) {
|
||
return -1;
|
||
}
|
||
unsigned long utime, stime, vsz, rss;
|
||
fgets(buffer, BUFFER_SIZE_PROC_STAT, fd);
|
||
// 14 utime 15 stime 23 24 vsz rss
|
||
// 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
|
||
sscanf(buffer, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %lu %lu %*s %*s %*s %*s %*s %*s %*s %*s %lu %lu ",
|
||
&utime, &stime, &vsz, &rss);
|
||
#if defined(LOG)
|
||
printf("ProcInfo:PID=%d,Name=%s,utime=%ld,stime=%ld,vsz=%ld,rss=%ld\n", proc->pid, proc->name, utime, stime, vsz,
|
||
rss);
|
||
#endif
|
||
|
||
proc->point++;
|
||
proc->point %= UPDATE_FREQUENCY;
|
||
proc->cpuInfo[proc->point].utime = utime;
|
||
proc->cpuInfo[proc->point].stime = stime;
|
||
proc->memInfo[proc->point].vsz = vsz;
|
||
proc->memInfo[proc->point].rss = rss * 4;
|
||
fclose(fd);
|
||
|
||
return 0;
|
||
}
|
||
|
||
void updateProcList() {
|
||
#if defined(LOG)
|
||
printf("/****** Proc Info ******/\n");
|
||
int i;
|
||
for (i = 0; i < LIMIT_PROCESS_NUMBER; i++) {
|
||
printf("id=%d,", Proc_List[i].pid);
|
||
}
|
||
printf("\n");
|
||
#endif
|
||
setFreeProcNode(1);
|
||
setFreeProcNode(101);
|
||
char file_path[64] = {0};
|
||
int currentProcNode;
|
||
for (currentProcNode = 0; currentProcNode < LIMIT_PROCESS_NUMBER; currentProcNode++) {
|
||
//check PID
|
||
if (Proc_List[currentProcNode].pid != 0) {
|
||
if (updateProcInfo(&Proc_List[currentProcNode]) == -1) {
|
||
//check path exist
|
||
sprintf(file_path, "/proc/%d", Proc_List[currentProcNode].pid);
|
||
if (access(file_path, F_OK)) {
|
||
freeProcInfo(&Proc_List[currentProcNode]);
|
||
}
|
||
};
|
||
}
|
||
}
|
||
return;
|
||
} |