Linux Vrss
Part1: Write a C program “hw1p1.c” to display the total of vrss sizes for all processes in the system using the ps command.
hw1p1.c: you need your C program to do the following in order to achieve this desired output.
(1) navigate the subfolders of the proc folder looking for those folders holding information about processes in the system. Remember that proc folder has such folders, named after the process pid number, and that the proc folder has other folders hosting data for other purposes.
(2) each time you locate a process folder you need to create a constant string array to hold the parameters needed to execute the proper ps command to retrieve the rss information for a process with specific pid. The command to retrieve that with ps is “ps -p pid -o rss”. The array should have these entries of the ps command as its elements and that last element in the array should be the NULL.
char *const parmList[] = {“ps”,”-p”,pid,”-o”,”rss”,NULL};
in this case pid is a string that you need to form based on the process pid which is the name of the folder.
(3) next you need to execute the ps command. To do so, you need to create a child process for this purpose who will then execute a proper exec system call that accepts two arguments, the path of the command to execute “/bin/ps” and the array you created earlier. This will be the execvp system call
execvp(“/bin/ps”, parmList);
The child needs to send its output to the parent then terminates hence, a pipe should be created before forking the child and a proper close/dup should be performed in the child code to get the result of execvp written to the pipe.
(4) the parent should wait to read the output of the child from the pipe and extract from it the value of rss without the heading then add that value to total.
(5) repeat the steps (2) to (4) for all folders holding information about processes in the system.
(6) display the total rss on the screen
Part2: Write a C program “hw1p2.c” to display the total of vrss sizes for all processes in the system by extracting the information from the status file of each process.
hw1p2.c: you need your C program to do the following in order to achieve this desired output.
(1) navigate the subfolders of the proc folder looking for those folders holding information about processes in the system. Remember that proc folder has such folders, named after the process pid number, and that the proc folder has other folders hosting data for other purposes.
(2) each time you locate a process folder you need to form a string hosting the path to the status file in that folder.
(3) use the path string to open the file.
(4) Remember that that the value of rss size is in the status file, open the file in gedit to understand the formats of it and to know how to locate the value of rss. Having done so, you can now code how to extract such information by read the file line by line. You can do that using a proper i/o method from those who are definded in stdio.h, for example, fscanf.
(5) each time you read a line, check if it contains the rss header which is “VmRSS:”. You can do that with the use of the C string function strstr. If the line contains the substring “VmRSS:” then it is the desired line having the value needed hence, you need to read the value using proper i/o method from those who are defined in stdio.h, for example, sscanf.
(6) add the retrieved value of rss to the total.
(7) repeat the steps (2) to (6) for all folders holding information about processes in the system.
(8) display the total rss on the screen.
HW1-p1.c
#include
#include
#include
#include
#include
#include
#include
int main()
{
DIR *d;
struct dirent *dir;
d = opendir(“/proc”);
int pfds[2];
int total;
int pid;
int rss;
char str[30];
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if(dir->d_type == DT_DIR)
{
if(isInt(dir->d_name))
{
//sprintf(“/proc/%s”,dir->d_name); // change name to string
snprintf(str , sizeof(str) , “%d” , dir->d_name);
char* const parmList[]={“ps”,”-p”
,dir->d_name,”-o”,”rss”,NULL};
pid=fork();
switch(pid){
case -1: printf(“fork failed.”);
break;
case 0: printf(“I am the child.\tx=%d\n”,pid);
close(1);
dup(pfds[1]);
close(pfds[0]);
execvp(“/bin/ps”,parmList);
break;
default: wait(NULL);
printf(“I am the Parent.\n”);
close(0);
dup(pfds[0]);
close(pfds[1]);
read(pfds[0],&rss ,sizeof(rss));
printf(“Current parent reading %d\n”,rss);
total+=rss;
printf(“Current parent reading sum %d\n”,total);
}
}
}
}
closedir(d);
printf(“total of rss = %d”,total);
}
}
int isInt(char *string)
{
int i, stringLength = strlen(string);
for(i = 0; i < stringLength; i++)
{
if(!isdigit(string[i]))
break;
}
if(i != stringLength)
return false;
else
return true;
}
HW1-p2.c
#include
#include
#include
#include
#include
#include
#include
#include
/* This program prints the full path of the status file for every
process who have a folder in the proc folder.
*/
int main()
{
char path [30];
DIR *d;
struct dirent *dir;
d = opendir(“/proc”);
int sum;
int rss;
FILE *fptr;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if(dir->d_type == DT_DIR)
{
if(isInt(dir->d_name))
{
sprintf(path,”/proc/%s/status”,dir->d_name);
printf(“%s\n”,path);
/* add the step 4,5,6,7,8*/
}
}
}
}
closedir(d);
}
}
int isInt(char *string)
{
int i, stringLength = strlen(string);
for(i = 0; i < stringLength; i++)
{
if(!isdigit(string[i]))
break;
}
if(i != stringLength)
return false;
else
return true;
}
Solution
HW1-p1.c
#include
#include
#include
#include
#include
#include
#include
int isInt(char *string);
int main()
{
DIR *d;
struct dirent *dir;
d = opendir(“/proc”);
int pfds[2];
int total = 0;
int pid;
char str[30];
FILE *in;
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if(dir->d_type == DT_DIR)
{
if(isInt(dir->d_name))
{
//sprintf(“/proc/%s”,dir->d_name); // change name to string
//sprintf(str, “%s” , dir->d_name);
char* const parmList[]={“ps”,”-p”,dir->d_name,”-o”,”rss”,NULL};
// create the pipe to read the output of the execvp
if (pipe(pfds) < 0) {
printf(“could not create pipe to execute `ps -p %s -o rss`.\n”, dir->d_name);
continue;
}
pid=fork();
switch(pid){
case -1: printf(“fork failed.”);
break;
case 0: //printf(“I am the child.\tx=%d\n”,pid);
dup2(pfds[1], STDOUT_FILENO);
close(pfds[0]);
execvp(“/bin/ps”,parmList);
break;
default: //printf(“I am the Parent.\n”);
close(pfds[1]);
in = fdopen(pfds[0], “r”);
fscanf(in, “%s”, str); // skip the header
if (fscanf(in, “%s”, str) == 1) { // read the RSS
int rss = atoi(str);
total += rss;
printf(“process %s rss=%d\n”, dir->d_name, rss);
}
// close the file and pipe
fclose(in);
close(pfds[0]);
break;
}
}
}
}
closedir(d);
printf(“\ntotal of rss = %d\n”,total);
}
}
int isInt(char *string)
{
int i, stringLength = strlen(string);
for(i = 0; i < stringLength; i++)
{
if(!isdigit(string[i]))
break;
}
if(i != stringLength)
return false;
else
return true;
}
HW1-p2.c
#include
#include
#include
#include
#include
#include
#include
#include
int isInt(char *string);
/* This program prints the full path of the status file for every
process who have a folder in the proc folder.
*/
int main()
{
char path [30];
DIR *d;
struct dirent *dir;
d = opendir(“/proc”);
int sum = 0;
int rss;
FILE *fptr;
char line[1024];
char ignored[32];
if (d)
{
while ((dir = readdir(d)) != NULL)
{
if(dir->d_type == DT_DIR)
{
if(isInt(dir->d_name))
{
sprintf(path,”/proc/%s/status”,dir->d_name);
printf(“%s\n”,path);
/* add the step 4,5,6,7,8*/
/* open the status file to read */
fptr = fopen(path, “r”);
if (fptr == NULL) {
printf(“could not read file %s.\n”, path);
continue;
}
/* read line by line to find the line starting with VmRSS: */
while (fgets(line, sizeof(line), fptr) != NULL) {
if (strstr(line, “VmRSS:”) == line) {
// read the second word as the rss size
// then accumulate the rss
if (sscanf(line, “%s %d”, ignored, &rss) == 2) {
printf(“rss = %d\n”, rss);
sum += rss;
}
break;
}
}
fclose(fptr);
}
}
}
closedir(d);
printf(“\ntotal of rss = %d\n”, sum);
}
return 0;
}
int isInt(char *string)
{
int i, stringLength = strlen(string);
for(i = 0; i < stringLength; i++)
{
if(!isdigit(string[i]))
break;
}
if(i != stringLength)
return false;
else
return true;
}