1 #include<stdlib.h>
2 #include<string.h>
3 #include<stdio.h>
4 #include<unistd.h>
5 #include<sys/time.h>
6 #include <sys/wait.h>
7 #include <sys/types.h>
8
9 #define SHELL "/bin/bash"
10 #define VMRSS_LINE 17
11 #define VMSIZE_LINE 13
12 #define PROCESS_TIME 14
13
14 typedef struct{
15 unsigned long user; //用户态的CPU时间
16 unsigned long nice; //nice值为负的进程所占用的CPU时间
17 unsigned long system;//核心时间
18 unsigned long idle; //硬盘IO等待时间以外其它等待时间
19 }Total_Cpu_Occupy_t;
20
21 typedef struct{
22 unsigned int pid;
23 unsigned long utime;
24 unsigned long stime;
25 unsigned long cutime;
26 unsigned long cstime;
27 }Proc_Cpu_Occupy_t;
28
29 const char* get_items(const char*buffer,unsigned int item)
30 {
31 const char*p=buffer;
32 int len = strlen(buffer);
33 int count=0;
34 for (int i=0;i<len;i++){
35 if(' '==*p){
36 count++;
37 if(count==item-1){
38 p++;
39 break;
40 }
41 }
42 p++;
43 }
44 return p;
45 }
47 unsigned long get_cpu_total_occupy(){ ///proc/stat文件从系统启动开始累计到当前时刻
48 FILE *fd;
49 char buff[1024]={0};
50 Total_Cpu_Occupy_t t;
51
52 fd=fopen("/proc/stat","r");
53 if(nullptr==fd){
54 return 0;
55 }
56
57 fgets(buff,sizeof(buff),fd); //fd中的信息赋给buff
58 char name[64]={0};
59 sscanf(buff,"%s %ld %ld %ld %ld",name,&t.user,&t.nice,&t.system,&t.idle);//从字符串中读> 取指定格式的数据 %ld long整数
60 fclose(fd);
61
62 return (t.user + t.nice + t.system + t.idle);
63 }
64
65 //获取进程的CPU时间
66 unsigned long get_cpu_proc_occupy(unsigned int pid){
67
68 char file_name[64]={0};
69 Proc_Cpu_Occupy_t t;
70 FILE *fd;
71 char line_buff[1024]={0};
72 sprintf(file_name,"/proc/%d/stat",pid);
73
74 fd = fopen(file_name,"r");
75 if(nullptr == fd){
76 return 0;
77 }
78
79 fgets(line_buff,sizeof(line_buff),fd);
80
81 sscanf(line_buff,"%u",&t.pid); //%u 十进制无符号整数
82 const char *q =get_items(line_buff,PROCESS_TIME);
83 sscanf(q,"%ld %ld %ld %ld",&t.utime,&t.stime,&t.cutime,&t.cstime);
84 fclose(fd);
85
86 return (t.utime + t.stime + t.cutime + t.cstime);
87 }
90 //获取CPU占用率
91 float get_proc_cpu(unsigned int pid){
92
93 unsigned long totalcputime1,totalcputime2;
94 unsigned long procputime1,procputime2;
95
96 totalcputime1=get_cpu_total_occupy();
97 procputime1=get_cpu_proc_occupy(pid);
98
99 usleep(200000);//0.2s
100
101 totalcputime2=get_cpu_total_occupy();
102 procputime2=get_cpu_proc_occupy(pid);
103
104 float pcpu = 0.0;
105 if(0 != totalcputime2-totalcputime1){
106 pcpu=100.0 * (procputime2-procputime1)/(totalcputime2-totalcputime1);
107 }
108
109 return pcpu;
110 }
113 //获取进程占用内存
114 unsigned int get_proc_mem(unsigned int pid){
115
116 char file_name[64]={0};
117 FILE *fd;
118 char line_buff[512]={0};
119 sprintf(file_name,"/proc/%d/status",pid);
120
121 fd =fopen(file_name,"r");
122 if(nullptr == fd){
123 return 0;
124 }
125
126 char name[64];
127 int vmrss;
128 for (int i=0; i<VMRSS_LINE-1;i++){
129 fgets(line_buff,sizeof(line_buff),fd);
130 }
131
132 fgets(line_buff,sizeof(line_buff),fd);
133 sscanf(line_buff,"%s %d",name,&vmrss);
134 fclose(fd);
135
136 return vmrss;
137 }
139
140 //获取进程占用虚拟内存
141 unsigned int get_proc_virtualmem(unsigned int pid){
142
143 char file_name[64]={0};
144 FILE *fd;
145 char line_buff[512]={0};
146 sprintf(file_name,"/proc/%d/status",pid);
147
148 fd =fopen(file_name,"r");
149 if(nullptr == fd){
150 return 0;
151 }
152
153 char name[64];
154 int vmsize;
155 for (int i=0; i<VMSIZE_LINE-1;i++){
156 fgets(line_buff,sizeof(line_buff),fd);
157 }
158
159 fgets(line_buff,sizeof(line_buff),fd);
160 sscanf(line_buff,"%s %d",name,&vmsize);
161 fclose(fd);
162
163 return vmsize;
164 }
167 //进程本身
168 int get_pid(const char* process_name, const char* user = nullptr)//根据进程名获得pid
169 {
170 if(user == nullptr){
171 user = getlogin(); //若没有输入用户名,则认为用户名为当前登录名
172 }
173
174 char cmd[512];
175 if (user){
176 sprintf(cmd, "pgrep %s -u %s", process_name, user); //cmd="pgrep process_name -u use r" 返回进程ID
177 }
178
179 FILE *pstr = popen(cmd,"r");
180
181 if(pstr == nullptr){
182 return 0;
183 }
184
185 char buff[512];
186 ::memset(buff, 0, sizeof(buff));
187 if(NULL == fgets(buff, 512, pstr)){//指定的流 stream 读取一行,并把它存储
188 return 0;
189 }
190
191 return atoi(buff); //返回整数
192 }
194 // 获取发送速率
195 static pid_t *childpid=nullptr;/*ptr to array allocated at run-time*/
196 static int maxfd; /*from our open_max(), {Prox openmax}*/
197 float readdata(int pid);
198
199 FILE *popen2(const char *cmdstring, const char *type)
200 {
201 int i, pfd[2];
202 pid_t pid;
203 FILE *fp;
204 if(type[0] != 'r' && type[0]!='w' || type[1] != 0) {
205 errno=EINVAL;
206 return (nullptr);
207 }
208 if(childpid == nullptr) { /*first time throngh, allocate zeroed out array for child pid s*/
209 maxfd = sysconf(_SC_OPEN_MAX);
210 if((childpid = (pid_t*)calloc(maxfd, sizeof(pid_t))) == nullptr)
211 return(nullptr);
212 }
213 if(pipe(pfd) < 0)
214 return(nullptr); //errno set by pipe()
215 if((pid = fork()) < 0)
216 return(nullptr); //error set by fork()
217 else if(pid==0) { /*child*/
218 if(*type == 'r') {
219 close(pfd[0]);
220 if(pfd[1] != STDOUT_FILENO) {
221 dup2(pfd[1], STDOUT_FILENO);
222 close(pfd[1]);
223 }
224 } else {
225 close(pfd[1]);
226 if(pfd[0] != STDIN_FILENO) {
227 dup2(pfd[0], STDIN_FILENO);
228 close(pfd[0]);
229 }
230 }
231 /*close all descriptiors in childpid*/
232 for(i = 0; i < maxfd; i++)
233 if(childpid[i] > 0)
234 close(i);
235 execl(SHELL, "bash", "-c", cmdstring, (char *)0);
236 _exit(127);
237 }
238
239 /*parent*/
240 if(*type == 'r') {
241 char lose(pfd[1]);
242 if((fp = fdopen(pfd[0], type)) == nullptr)
243 return (nullptr);
244 }else {
245 close(pfd[0]);
246 if((fp = fdopen(pfd[1], type)) == nullptr)
247 return (nullptr);
248 }
249 childpid[fileno(fp)] = pid; /*remember child pid for this fd*/
250 return(fp);
251 }
252
253 int pclose2(FILE *fp)
254 {
255 int fd, stat;
256 pid_t pid;
257 //printf("hello>>>>>>>>>>>>>\n");
258 if(childpid == nullptr) /*popen() has never benn called*/
259 return (-1);
260
261 fd = fileno(fp);
262 if((pid = childpid[fd]) == 0)
263 return (-1); //fp wasn't opened by popen()
264
265 childpid[fd] = 0;
266 if(fclose(fp) == EOF)
267 return (-1);
268 if( kill(pid, SIGKILL) != 0) {
269 printf("kill failed\n");
270 perror("kill");
271 }
272 else {
273 // printf("%d killed\n", pid);
274 }
275 while(waitpid(pid, &stat, 0) < 0) {
276 if(errno != EINTR )
277 return (-1); /*error other than EINTR from waitpid()*/
278 }
279
280 return(stat);
281 }
284 //输出发送速率到log.txt
285 float get_send( int pid)
286 {
287 char cmd[512]="sudo nethogs -a -t>log.txt";
288 //printf("cmd=%s\n",cmd);
289 FILE *pstr = popen2(cmd,"r");
290 if(nullptr == pstr){
291 printf("打开nethogs命令失败!\n");
292 return -1;
293 }
294 usleep(500000);
295 pclose2(pstr);
296 usleep(500000);
297 float read_rate;
298 read_rate = readdata(pid);
299
300 return read_rate;
301 }
302 float readdata( int pid) //从log.txt中读取发送速率
303 {
304 //创建文件流,文件指针名=fopen(文件名,使用文件方式)打开失败则返回NULL;
305 FILE *fp=fopen("./log.txt","r");
306 //检测文件是否打开成功;
307 if(!fp){
308 printf("TXT打开失败!\n");
309 return -1; //返回异常
310 }
311 char name[10];
312 char third[10];
313 char readpid[5];
314 float sendrate,recerata; //用来储存收发速度
315 fscanf(fp, "%*c%*[^\n]%*c");
316 fscanf(fp, "%*c%*[^\n]%*c");
317 fscanf(fp, "%*c%*[^\n]%*c");
318 fscanf(fp, "%*c%*[^\n]%*c");
319 fscanf(fp, "%*c%*[^\n]%*c");
320 fscanf(fp, "%*c%*[^\n]%*c");
321 fscanf(fp, "%*c%*[^\n]%*c");
322 fscanf(fp, "%*c%*[^\n]%*c");
323 fscanf(fp, "%*c%*[^\n]%*c");
324 //fscanf(fp,"./%[^'/']/%[^'/']/%s %f %f\n",&name,&readpid,&third,&sendrate,&recerata);
325 //printf("pid=%d\n",pid);
326 while(fscanf(fp,"./%[^'/']/%[^'/']/%s %f %f\n",&name,&readpid,&third,&sendrate,&recerata )>0){
327 // printf("%s %s %s %lf %lf",&name,&readpid,&third,sendrate,recerata);
328 if(pid==atoi(readpid)){
329 // printf("%s %s %s %lf %lf",&name,&readpid,&third,sendrate,recerata);
330 printf("成功读取发送速率!\n");
331 fclose(fp);
332 return sendrate;
333 }
334 }
335 printf("read sendrate fail!\n");
336 fclose(fp);
337 return 0;
338 }
339
340 int main(int argc, char *argv[])
341 {
342 while(1){
343
344 if(argc < 2){
345 printf("Usage:test <process_name> [user]\n");//调用格式: ./getinfo 进程名
346 return 1;
347 }
348
349 unsigned int pid=0;
350
351 if(argc > 2){
352 pid = get_pid(argv[1],argv[2]);
353 }
354 else{
355 pid = get_pid(argv[1]);
356 }
357
358 printf("pid=%d\n",pid);
359 printf("pcpu=%f\n",get_proc_cpu(pid));
360 printf("procmem=%d\n",get_proc_mem(pid));
361 printf("virtualmem=%d\n",get_proc_virtualmem(pid));
362 printf("sendrate=%lf\n",get_send(pid));
363 printf("-----------------------------------------\n");
364 usleep(2000000);
365 }
367 return 0;
368 }
编译:
运行: