当前位置: 首页 > 工具软件 > Nethogs > 使用案例 >

linux 使用Nethogs监控进程的发送速率

邵诚
2023-12-01

使用Nethogs监控进程的发送数据速率

先利用nethogs将进程的收发速率写进log文件,再对文件进行读取

  1 #define SHELL "/bin/bash"                                                                   
  2 #include<string.h>
  3 #include<stdlib.h>
  4 #include<sys/time.h>
  5 #include<stdio.h>
  6 #include<unistd.h>
  7 #include<iostream>
  8 #include <sys/types.h>
  9 #include <sys/wait.h>
 10 
 11 static pid_t *childpid=NULL;/*ptr to array allocated at run-time*/
 12 static int maxfd; /*from our open_max(), {Prox openmax}*/
 13 float readdata(int pid);
   //这里由于Nethogs打开之后需要关闭 而popen函数并不对于子进程进行操作,只是等命令进行完之后再进一步继续,因此需要重写popen函数,在pclose时对子进程kill
 20 FILE *popen2(const char *cmdstring, const char *type)
 21 {                                                                                           
 22     int i, pfd[2];
 23     pid_t pid;
 24     FILE *fp;
 25 
 26     /*only allow "r" or "w"*/
 27     if(type[0] != 'r' && type[0]!='w' || type[1] != 0) {
 28         errno=EINVAL;
 29         return (NULL);
 30     }
 31     if(childpid == NULL) {/*first time throngh, allocate zeroed out array for child pids*/
 32         maxfd = sysconf(_SC_OPEN_MAX);
 33         if((childpid =(pid_t*) calloc(maxfd, sizeof(pid_t))) == NULL){
 34             return(NULL);
 35         }
 36     }
 37     if(pipe(pfd) < 0){
 38         return(NULL);
 39     }           //errno set by pipe()
 40     if((pid = fork()) < 0){
 41         return(NULL);  //error set by fork()
 42     }
 43     else if(pid==0) {  /*child*/
 44         if(*type == 'r') {
 45             close(pfd[0]);
 46             if(pfd[1] != STDOUT_FILENO) {
 47                 dup2(pfd[1], STDOUT_FILENO);
 48                 close(pfd[1]);
 49             }
 50         } else {
 51             close(pfd[1]);
 52             if(pfd[0] != STDIN_FILENO) {
 53                 dup2(pfd[0], STDIN_FILENO);
 54                 close(pfd[0]);
 55             }
 56         }
 57         /*close all descriptiors in childpid*/
 58         for(i = 0; i < maxfd; i++)
 59             if(childpid[i] > 0)
 60                 close(i);
 61         execl(SHELL, "bash", "-c", cmdstring, (char *)0);
 62         _exit(127);
 63     }
 64 
 65     /*parent*/
 66     if(*type == 'r') {
 67         close(pfd[1]);
 68         if((fp = fdopen(pfd[0], type)) == NULL)
 69             return (NULL);
 70     }else {
 71         close(pfd[0]);
 72         if((fp = fdopen(pfd[1], type)) == NULL)
 73             return (NULL);
 74     }
 75     childpid[fileno(fp)] = pid; /*remember child pid for this fd*/
 76     return(fp);
 77 }
 78 
 79 
 80 int pclose2(FILE *fp)
 81 {
 82     int fd, stat;
 83     pid_t pid;
 84     printf("hello>>>>>>>>>>>>>\n");
 85     if(childpid == NULL) /*popen() has never benn called*/
 86         return (-1);
 87 
 88     fd = fileno(fp);
 89     if((pid = childpid[fd]) == 0)
 90         return (-1); //fp wasn't opened by popen()
 91 
 92     childpid[fd] = 0;
 93     if(fclose(fp) == EOF)
 94         return (-1);
 95     if( kill(pid, SIGKILL) != 0) {
 96         printf("kill failed\n");                                                            
 97         perror("kill");
 98     }
 99     else {
100         printf("%d killed\n", pid);
101     }
110 int get_pid(const char* process_name, const char* user = nullptr)//根据进程名获得pid
111 {
112      if(user == nullptr){
113          user = getlogin();  //若没有输入用户名,则认为用户名为当前登录名
114      }
115 
116      char cmd[512];
117      if (user){
118          sprintf(cmd, "pgrep %s -u %s", process_name, user); //cmd="pgrep process_name -u us    er" 返回进程ID
119      }
120 
121      FILE *pstr = popen(cmd,"r");
122 
123      if(pstr == nullptr){
124          return 0;
125      }
126 
127      char buff[512];
128      ::memset(buff, 0, sizeof(buff));
129      if(NULL == fgets(buff, 512, pstr)){//指定的流 stream 读取一行,并把它存储
130          return 0;
131      }
132 
133      return atoi(buff); //返回整数
134 }
138 //输出发送速率到log.txt
139 float get_send(int pid)
140 {
141     char cmd[512]="sudo nethogs -a -t>log.txt";    //这里一定要是trace模式,不然写进去是乱码,不懂为什么
142     //printf("cmd=%s\n",cmd);
143     FILE *pstr = popen2(cmd,"r");
144     if(nullptr == pstr){
145         printf("打开nethogs命令失败!\n");
146         return -1;
147     }
148     usleep(500000);  //这里需要注意,写进文件之后需要一定时间才可以进行操作。
149     pclose2(pstr);
150     usleep(500000);  
151     float read_rate;
152     read_rate = readdata(pid);
153 
154     return read_rate;
155 }
157 float readdata(int pid) //从log.txt中读取发送速率
158 {
159     //创建文件流,文件指针名=fopen(文件名,使用文件方式)打开失败则返回NULL;
160     FILE *fp=fopen("./log.txt","r");
161     //检测文件是否打开成功;
162     if(!fp){
163         printf("打开失败!\n");
164         return -1; //返回异常
165     }
166     char name[10];
167     char third[10];
168     char readpid[5];
169     float sendrate,recerata; //用来储存收发速度
170     fscanf(fp, "%*c%*[^\n]%*c");
171     fscanf(fp, "%*c%*[^\n]%*c");
172     fscanf(fp, "%*c%*[^\n]%*c");
173     fscanf(fp, "%*c%*[^\n]%*c");
174     fscanf(fp, "%*c%*[^\n]%*c");
175     fscanf(fp, "%*c%*[^\n]%*c");
176     fscanf(fp, "%*c%*[^\n]%*c");
177     fscanf(fp, "%*c%*[^\n]%*c");
178     fscanf(fp, "%*c%*[^\n]%*c");
181     while(fscanf(fp,"./%[^'/']/%[^'/']/%s %f %f\n",&name,&readpid,&third,&sendrate,&recerata )>0){
182         printf("%s %s %s %lf %lf",&name,&readpid,&third,sendrate,recerata);
183         if(pid==atoi(readpid)){
184             printf("%s %s %s %lf %lf",&name,&readpid,&third,sendrate,recerata);
185             printf("成功读取发送速率!\n");
186             fclose(fp);
187             return sendrate;
188         }
189     }
190     printf("read sendrate fail!\n");
191     fclose(fp);                                                                             
192     return 0;
193 }
195 int main(int argc, char *argv[])
196 {
197     while(1){
198 
199     if(argc < 2){
200         printf("Usage:test <process_name> [user]\n");//调用格式:  ./getinfo >    进程名
201         return 1;
202     }
203     
204     unsigned int pid=0;
205     
206     if(argc > 2){
207         pid = get_pid(argv[1],argv[2]);
208     }
209     else{
210         pid = get_pid(argv[1]);
211     }   
212     printf("pid=%d\n",pid);
213     printf("send=%lf\n",get_send(pid)); 
214     usleep(2000000);
215 }
216 
217     return 0;                                                                 
218 }

参考

重写的popen函数:https://blog.csdn.net/w18mc0431/article/details/52132447
单步调试正确,但是运行错误:https://blog.csdn.net/duguduchong/article/details/5998152?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control&dist_request_id=&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.control

 类似资料: