// // Created by Iain on 2021/7/17. // #include "ProcessInfo.h" #include #include #include #include #include #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; }