/****************************************************************** * Created: Josep Valls 20080211 * Process monitor for CMPS105/Winter2008 * Practice the use of the /proc file system * Features: lists process, refreshes automatically * Wishlist: order by cpu usage, memory size, user..., ******************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include typedef struct{ pid_t pid; char comm[255]; char state; long size; long cpu; long cpup; uid_t uid; } s_jobs; void printEnvironmentInformation(); void printGeneralInformation(); void print_time(char* label, long time); int sortJobsCmp (const struct s_jobs *c1, const struct s_jobs *c2){ //return strcmp(&c1->comm, &c2->comm); //if(&c1->size>&c2->size) return 1; return 0; return (int)(random()*2); //return -1; } int main(int argc, char *argv[]) { DIR *cdir; struct dirent *cdirc; FILE *fp; char *dirname=(char *) malloc(255*sizeof(char)); int procid; char *procname[255]; struct stat st; s_jobs jobs[1000]; int i; int itmp; char ctmp; long ltmp,ttmp; //print some general information, maybe optional commandline printEnvironmentInformation(); printGeneralInformation(); //main loop //traverse the /proc file system do{ procid=0; ttmp=0; if(cdir=opendir("/proc/")){ while(cdirc=readdir(cdir)){ if (strcmp(cdirc->d_name, ".") == 0) continue; if (strcmp(cdirc->d_name, "..") == 0) continue; if (cdirc->d_type==DT_DIR){ if (strspn(cdirc->d_name, "0123456789") == strlen(cdirc->d_name)){ //check if it is only numeric, more likely to be a process strcpy(dirname,"/proc/"); strcat(dirname,cdirc->d_name); strcat(dirname,"/stat"); //printf("%s\n",dirname); if(fp=fopen((char *)dirname, "r")){ fstat(fp,&st); jobs[procid].uid=st.st_uid; fscanf(fp,"%d %s %c", &jobs[procid].pid, &jobs[procid].comm,&jobs[procid].state); //skip all the fields that we don't need fscanf(fp,"%d",&itmp); fscanf(fp,"%d",&itmp); fscanf(fp,"%d",&itmp); fscanf(fp,"%d",&itmp); fscanf(fp,"%d",&itmp); fscanf(fp,"%lu",<mp); fscanf(fp,"%lu",<mp); fscanf(fp,"%lu",<mp); fscanf(fp,"%lu",<mp); fscanf(fp,"%lu",<mp); //get the old cpu jiffles ltmp=jobs[procid].cpu; fscanf(fp,"%lu",&jobs[procid].cpu); jobs[procid].cpup=jobs[procid].cpu-ltmp; ttmp+=jobs[procid].cpup; printf("%d %d\n",ttmp,jobs[procid].cpup); fscanf(fp,"%lu",<mp); fscanf(fp,"%ld",<mp); fscanf(fp,"%ld",<mp); fscanf(fp,"%ld",<mp); fscanf(fp,"%ld",<mp); fscanf(fp,"%ld",<mp); fscanf(fp,"%ld",<mp); fscanf(fp,"%lu",<mp); fscanf(fp,"%lu", &jobs[procid].size); fclose(fp); //printf("%s %c %d\n",jobs[procid].comm,jobs[procid].state,jobs[procid].size); procid++; } } } } closedir(cdir); //update cpu usage for (i = 0; i < procid-1; i++){ jobs[i].cpup=jobs[i].cpup*100/ttmp; } /* printf("PID\t STAT\t CPU%%\t SIZE\t COMMAND\n"); for (i = 0; i < procid-1; i++) printf("%d\t %c\t %d\t %d\t %s\n",jobs[i].pid, jobs[i].state, jobs[i].cpup, jobs[i].size, jobs[i].comm); printf("-------------------------------------------\n"); */ qsort (jobs, procid-1, sizeof(s_jobs), sortJobsCmp); //Print the information printf("PID\t STAT\t CPU%%\t SIZE\t USER\t COMMAND\n"); for (i = 0; i < procid-1&&i<20; i++) printf("%d\t %c\t %d\t %dk\t %d %s\n",jobs[i].pid, jobs[i].state, jobs[i].cpup, (int)jobs[i].size/1024, jobs[i].uid, jobs[i].comm); }else{ printf("Error opening directory /proc. Errno = %d.\n",errno); printf(" %s.\n", strerror(errno)); } printf("control+c to quit\n"); //time refresh routine... not very accurate i fear... struct timeval tv; int retval, milisec; milisec=3000; tv.tv_sec = (milisec - (milisec % 1000)) / 1000; tv.tv_usec = (milisec - (tv.tv_sec * 1000)) * 1000; retval = select(0, NULL, NULL, NULL, &tv); if(retval == -1) perror("select()"); else printf("Slept for %d milliseconds,refreshing\n", milisec); }while(1); } void printEnvironmentInformation(){ int i; char **ptr; extern char **environ; for(ptr=environ; *ptr!=0; ptr++){ printf("%s\n",*ptr); } } void printGeneralInformation(){ FILE* fp; double uptime, idle_time; /* Read the system uptime and accumulated idle time from /proc/uptime. */ fp = fopen ("/proc/uptime", "r"); fscanf (fp, "%lf %lf\n", &uptime, &idle_time); fclose (fp); print_time ("uptime ", (long) uptime); print_time ("idle time ", (long) idle_time); } void print_time(char* label, long time){ const long minute = 60; const long hour = minute * 60; const long day = hour * 24; printf ("%s: %ld days, %ld:%02ld:%02ld\n",label, time / day, (time % day) / hour, (time % hour) / minute, time % minute); }