RDK Documentation (Open Sourced RDK Components)
dcaprocess.cpp
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 
20 
21 
22 /**
23 * @defgroup dca
24 * @{
25 **/
26 
27 
28 
29 
30 /**
31 * @defgroup dca
32 * @{
33 * @defgroup src
34 * @{
35 **/
36 
37 
38 #include <iostream>
39 #include <stdio.h>
40 #include <string.h>
41 #include <sys/stat.h>
42 #include <fcntl.h> /* Definition of AT_* constants */
43 #include <unistd.h>
44 #include <unistd.h>
45 #include <math.h>
46 #include <ios>
47 #include <fstream>
48 #include <string>
49 #include <cstring>
50 #include <cstdlib>
51 #include "safec_lib.h"
52 
53 
54 #define LEN 14
55 #define BUF_LEN 16
56 #define CMD_LEN 256
57 #define MAXLEN 512
58 #define PID_SIZE 10
59 #define PIDOF_SIZE 50
60 #define MEM_STRING_SIZE 20
61 #define PROC_PATH_SIZE 50
62 
63 using namespace std;
64 
65 
66 #ifndef ENABLE_XCAM_SUPPORT
67 
68 typedef struct _procMemCpuInfo {
69  char processName[BUF_LEN];
70  char cpuUse[BUF_LEN];
71  char memUse[BUF_LEN];
73 
74 
75 bool getProcInfo(procMemCpuInfo *pInfo);
76 
77 int main(int argc,char *argv[]) {
78  FILE *in = NULL;
79  char *processName = NULL;
80  FILE *fp = NULL ;
81  procMemCpuInfo pInfo = { 0 };
82  errno_t rc = -1;
83 
84  if(argv[1] == NULL)
85  {
86  return 0;
87  }
88 
89  processName = argv[1];
90 
91  if (processName != NULL) {
92  rc = memcpy_s(pInfo.processName, sizeof(pInfo.processName), processName, strlen(processName)+1);
93  if(rc != EOK)
94  {
95  ERR_CHK(rc);
96  return 0;
97  }
98  }
99 
100 
101 
102  if(false == getProcInfo(&pInfo))
103  {
104  cout << "{\"Failed\":\"0\"}";
105  return 0;
106  }
107 
108  cout << "{\"mem_" << processName << "\":\"" << pInfo.memUse << "\"},";
109  cout << "{\"cpu_" << processName << "\":\"" << pInfo.cpuUse << "\"}";
110 
111  return 1;
112 }
113 
114 /**
115  * @addtogroup DCA_APIS
116  * @{
117  */
118 
119 
120 /**
121  * @brief To get the reserve memory of a given process in pages.
122  *
123  * @param[in] pInfo Process Name.
124  * @param[in] processPid Process Id.
125  *
126  * @return Returns reserve memory of the requested process.
127  */
128 char* getResidentMemory(procMemCpuInfo *pInfo, int* processPid)
129 {
130  using std::ios_base;
131  using std::ifstream;
132  using std::string;
133  char procPath[PROC_PATH_SIZE];
134  static char retMem[MEM_STRING_SIZE];
135  int intStr = 0,intValue = 0;
136  long pageSizeInKb = sysconf(_SC_PAGE_SIZE) / 1024; /* x86-64 is configured to use 2MB pages */
137  errno_t rc = -1;
138 
139  /* Use /proc/<pid>/statm (see man page for proc)
140  * statm is made up of size, resident, shared, text, lib, data
141  * and dt columns.
142  * We only require resident memory, so read the 1st 2 columns.
143  */
144  /* Set procPath */
145  rc = sprintf_s(procPath,sizeof(procPath),"/proc/%d/statm", *processPid);
146  if(rc < EOK)
147  {
148  ERR_CHK(rc);
149  return NULL;
150  }
151 
152  ifstream statm(procPath);
153  int totalMemory, residentMemory;
154  statm >> totalMemory >> residentMemory;
155  statm.close();
156 
157  residentMemory *= pageSizeInKb;
158  intStr = (int)residentMemory;
159  intValue = intStr;
160  if (intValue >= 1024)
161  intStr = intStr/1024;
162  rc = sprintf_s(retMem,sizeof(retMem),"%d%s", intStr,(intValue >= 1024) ? "m" : "k");
163  if(rc < EOK)
164  {
165  ERR_CHK(rc);
166  return NULL;
167  }
168 
169  return retMem;
170 }
171 
172 bool getProcInfo(procMemCpuInfo *pInfo)
173 {
174  bool ret = false;
175  FILE *inFp = NULL;
176  char command[CMD_LEN] = {'\0'};
177  char *pcpu = NULL, *pmem = NULL;
178  char var1[BUF_LEN] = {'\0'};
179  char var2[BUF_LEN] = {'\0'};
180  char var3[BUF_LEN] = {'\0'};
181  char var4[BUF_LEN] = {'\0'};
182  char var5[BUF_LEN] = {'\0'};
183  char var6[BUF_LEN] = {'\0'};
184  char var7[BUF_LEN] = {'\0'};
185  char var8[512]= {'\0'};
186  char var9[512]= {'\0'};
187  char var10[512]= {'\0'};
188  int pid = 0;
189  errno_t rc = -1;
190 
191  if (pInfo == NULL) {
192 
193  return false;
194  }
195 
196  rc = sprintf_s(command,sizeof(command),"pidof %s", pInfo->processName);
197  if(rc < EOK)
198  {
199  ERR_CHK(rc);
200  return false;
201  }
202  if(!(inFp = popen(command, "r"))){
203  return false;
204  }
205  fscanf(inFp,"%d",&pid);
206  pclose(inFp);
207  if( pid == 0) {
208  return false;
209  }
210 
211 #ifdef INTEL
212  #ifdef YOCTO_BUILD
213  /* Format Use: `top -b -n 1 | grep Receiver` */
214  rc = sprintf_s(command,sizeof(command),"top -b -n 1 | sed 's/^[ \t]*//' | grep \"^%d\"", pid);
215 
216  #else
217  /* Format Use: `top -n 1 | grep Receiver` */
218  rc = sprintf_s(command,sizeof(command),"top -n 1 | grep -i '%s'", pInfo->processName);
219  #endif
220 
221 #else
222  /* ps -C Receiver -o %cpu -o %mem */
223  //sprintf(command, "ps -C '%s' -o %%cpu -o %%mem | sed 1d", pInfo->processName);
224  rc = sprintf_s(command,sizeof(command),"top -b -n 1 | grep -i '%s'", pInfo->processName);
225 #endif
226  if(rc < EOK)
227  {
228  ERR_CHK(rc);
229  return false;
230  }
231 
232  if(!(inFp = popen(command, "r"))){
233  return false;
234  }
235 
236 
237  // 2268 root 20 0 831m 66m 20m S 27 13.1 491:06.82 Receiver
238 #ifdef INTEL
239  if (fscanf(inFp,"%s %s %s %s %s %s %s %s", var1, var2, var3, var4, var5, var6, var7, var8) == 8) {
240  pcpu = var7;
241  }
242 //#endif
243 #else
244 //while(fscanf(inFp,"%s %s", var1, var2) == 2)
245 // {
246 // pcpu = var1;
247 // pmem = var2;
248  // }
249  if (fscanf(inFp,"%s %s %s %s %s %s %s %s %s %s", var1, var2, var3, var4, var5, var6, var7, var8, var9, var10) == 10) {
250  pcpu = var9;
251  }
252 #endif
253  pclose(inFp);
254  /* Get the resident memory value. Take from proc/$pid/stats */
255  pmem = getResidentMemory(pInfo, &pid);
256 
257  if ((pcpu != NULL) && (pmem != NULL)) {
258  rc = strcpy_s(pInfo->cpuUse,sizeof(pInfo->cpuUse),pcpu);
259  if(rc != EOK)
260  {
261  ERR_CHK(rc);
262  return false;
263  }
264  rc = strcpy_s(pInfo->memUse,sizeof(pInfo->memUse),pmem);
265  if(rc != EOK)
266  {
267  ERR_CHK(rc);
268  return false;
269  }
270  ret = true;
271  }
272 
273  return ret;
274 
275 }
276 #else //ENABLE_XCAM_SUPPORT
277 typedef struct proc_info {
278  /* See man page for proc for details of fields. */
279  int utime;
280  int stime;
281  int cutime;
282  int cstime;
283  unsigned int rss;
284 } procinfo;
285 
286 /**
287  * @brief To get process information of the process.
288  *
289  * @param[in] pid Process Id of process.
290  * @param[in] pinfo Address of process object of process.
291  *
292  * @return Returns status of operation.
293  * @retval True on success.
294  */
295 bool getProcInfo(int pid, procinfo * pinfo)
296 {
297  char szFileName [CMD_LEN],szStatStr [2048],*s, *t;
298  FILE *fp;
299  struct stat st;
300  int ppid, pgrp, session, tty, tpgid, counter, priority, starttime, signal, blocked, sigignore, sigcatch;
301  char exName [CMD_LEN], state;
302  unsigned euid, egid;
303  unsigned int flags, minflt, cminflt, majflt, cmajflt, timeout, itrealvalue, vsize, rlim, startcode, endcode, startstack, kstkesp, kstkeip, wchan, rss;
304  errno_t rc = -1;
305 
306  if (NULL == pinfo)
307  {
308  cout << "Invalid input(pinfo=NULL) to get process info"<<endl;
309  return false;
310  }
311 
312  rc = sprintf_s(szFileName,sizeof(szFileName),"/proc/%u/stat", (unsigned) pid);
313  if(rc < EOK)
314  {
315  ERR_CHK(rc);
316  return false;
317  }
318 
319  if (-1 == access (szFileName, R_OK))
320  {
321  cout << "Unable to access file in get proc info"<<endl;
322  return false;
323  }
324 
325  if (-1 != stat (szFileName, &st))
326  {
327  euid = st.st_uid;
328  egid = st.st_gid;
329  }
330  else
331  {
332  euid = egid = -1;
333  }
334 
335  if ((fp = fopen (szFileName, "r")) == NULL)
336  {
337  cout << "Failed to open file in get process info"<<endl;
338  return false;
339  }
340 
341  if ((s = fgets (szStatStr, 2048, fp)) == NULL)
342  {
343  fclose (fp);
344  }
345 
346  /** pid **/
347  s = strchr (szStatStr, '(') + 1;
348  t = strchr (szStatStr, ')');
349  rc = strncpy_s(exName,sizeof(exName),s,t - s);
350  if(rc != EOK)
351  {
352  ERR_CHK(rc);
353  fclose (fp);
354  return false;
355  }
356  exName [t - s] = '\0';
357 
358  /* Refer to /proc/[pid]/stat from proc man-page.*/
359  sscanf (t + 2, "%c %d %d %d %d %d %u %u %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d %d %d %d %u",
360  /* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33*/
361  &(state), &(ppid), &(pgrp), &(session), &(tty), &(tpgid), &(flags),
362  &(minflt), &(cminflt), &(majflt), &(cmajflt), &(pinfo->utime),
363  &(pinfo->stime), &(pinfo->cutime), &(pinfo->cstime), &(counter),
364  &(priority), &(timeout), &(itrealvalue), &(starttime),
365  &(vsize), &(pinfo->rss), &(rlim), &(startcode), &(endcode),
366  &(startstack), &(kstkesp), &(kstkeip), &(signal), &(blocked),
367  &(sigignore), &(sigcatch), &(wchan));
368 
369  fclose (fp);
370 
371  return true;
372 }
373 
374 /**
375  * @brief To get total CPU time of the device.
376  *
377  * @param[in] totalTime Total time of device.
378  *
379  * @return Returns status of operation.
380  * @retval True on success.
381  */
382 int getTotalCpuTimes(int * totalTime)
383 {
384  FILE *fp;
385  long double a[10];
386  int total;
387 
388  fp = fopen("/proc/stat","r");
389 
390  if(!fp)
391  return false;
392 
393  fscanf(fp,"%*s %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf %Lf",
394  &a[0],&a[1],&a[2],&a[3],&a[4],&a[5],&a[6],&a[7],&a[8],&a[9]);
395  fclose(fp);
396  total = (a[0]+a[1]+a[2]+a[3]+a[4]+a[5]+a[6]+a[7]+a[8]+a[9]);
397  *totalTime = total;
398 
399  return true;
400 }
401 
402 /**
403  * @brief To get process CPU utilization of the process.
404  *
405  * @param[in] pid Process id of process.
406  * @param[in] procCpuUtil Process cpu utilization of process.
407  *
408  * @return Returns status of operation.
409  * @retval True on success.
410  */
411 bool getProcessCpuUtilization(int pid, float *procCpuUtil)
412 {
413  char cpuUtilizationProc[MAXLEN]={'\0'};
414  procinfo pinfo1;
415  int no_cpu;
416  float total_time_process[2],time[2];
417  int t[2];
418  float sub1;
419  float time1;
420  float util=0;
421 
422 
423  no_cpu=sysconf(_SC_NPROCESSORS_ONLN);
424  if( false == getProcInfo(pid, &pinfo1))
425  return false;
426 
427  total_time_process[0]= pinfo1.utime +
428  pinfo1.stime +
429  pinfo1.cutime +
430  pinfo1.cstime;
431  //start=pinfo1.starttime;
432 
433  if( !getTotalCpuTimes(&t[0]) )
434  return false;
435 
436  time[0] = t[0];
437  sleep(2);
438 
439  if( false == getProcInfo(pid,&pinfo1))
440  return false;
441 
442  total_time_process[1]= pinfo1.utime +
443  pinfo1.stime +
444  pinfo1.cutime +
445  pinfo1.cstime;
446 
447  if( false == getTotalCpuTimes(&t[1]) )
448  return false;
449 
450  time[1] = t[1];
451  sub1 = total_time_process[1]-total_time_process[0];
452  time1= time[1] - time[0];
453  //util = (sub1/time1)*100*no_cpu;
454  util = (sub1/time1)*100;
455 
456  // round off to 2 decimal points
457  util = roundf(util * 100)/100;
458 
459  if(procCpuUtil)
460  *procCpuUtil = util;
461  else
462  return false;
463 
464  return true;
465 
466 }
467 
468 
469 int main(int argc,char *argv[]) {
470  char *processName = NULL;
471  procinfo pInfo = { 0 };
472  char command[CMD_LEN] = {'\0'};
473  int pid = 0;
474  float cpu = 0.0;
475  FILE *inFp = NULL;
476  int pagesize_kb = 0;
477  errno_t rc = -1;
478 
479  if(argv[1] == NULL)
480  {
481  cout<<"No Arguments passed!"<<endl;
482  return false;
483  }
484 
485  processName = argv[1];
486  rc = sprintf_s(command,sizeof(command),"pidof %s", processName);
487  if(rc < EOK)
488  {
489  ERR_CHK(rc);
490  return false;
491  }
492 
493 
494  if(!(inFp = popen(command, "r"))){
495  return false;
496  }
497 
498  fscanf(inFp,"%d",&pid);
499  pclose(inFp);
500 
501  if(pid)
502  {
503  if(false == getProcInfo(pid,&pInfo))
504  {
505  cout << "{\"Failed\":\"0\"}";
506  return false;
507  }
508  }
509  else
510  {
511  return false;
512  }
513 
514  getProcessCpuUtilization(pid,&cpu);
515 
516  pagesize_kb = getpagesize()/1024;
517  cout << "{\"mem_" << processName << "\":\"" << (pInfo.rss) * pagesize_kb << "\"},";
518  cout << "{\"cpu_" << processName << "\":\"" << cpu << "\"}";
519 
520  return true;
521 }
522 
523 
524 #endif //ENABLE_XCAM_SUPPORT
525 
526 /** @} */ //END OF GROUP DCA_APIS
527 
528 /** @} */
529 
530 
531 /** @} */
532 /** @} */
proc_info::stime
int stime
Definition: dcaproc.c:72
_procMemCpuInfo
Definition: dcaproc.c:78
proc_info::cstime
int cstime
Definition: dcaproc.c:74
proc_info::cutime
int cutime
Definition: dcaproc.c:73
proc_info::utime
int utime
Definition: dcaproc.c:71
proc_info::rss
unsigned int rss
Definition: dcaproc.c:75
getResidentMemory
char * getResidentMemory(procMemCpuInfo *pInfo, int *processPid)
To get the reserve memory of a given process in pages.
Definition: dcaprocess.cpp:128
getProcInfo
int getProcInfo(procMemCpuInfo *pInfo)
To get CPU and mem info.
Definition: dcaproc.c:397
proc_info
Definition: dcaproc.c:70