I am trying to write a program that takes a few processes as its arguments. Then the parent process executes each child process and prints out a few statistics with regard to the same.
Example: /generate ls -l //Would result in a program that prints out some statistics with regard to ls -l (Specifically its system time, user time and number of context switches).
Instead of using the getrusage() function, I would like to get the necessary information from the Proc file system. Now my understanding is that if I were to use a wait() function, it would end up removing the information from my proc file system. I have included my code below
#include <time.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
void inputted_command(int a, char **b){
for(int i=1;i<a;i++)
printf("%s ",b[i]);
}
int main(int argc, char **argv){
int status;
pid_t childpid;
pid_t get_information;
if (argc < 2)
{
return 1;
}
bool handle_signals = (signal(SIGINT, SIG_IGN) != SIG_IGN);
clock_t t;
t= clock();
pid_t pid = fork();
if(pid<0)
{
printf("fork: error no = %s\n",strerror(errno));
return 1;
}
else if(pid>0){
signal(SIGINT,SIG_IGN);
sleep(60);
/*
get_information=fork();
if(get_information==0){
excelp(___);
}else
waitpid(pid, &status, 0);
*/
waitpid(childpid, &status, 0);
t= clock()-t;
double real_time_taken = ((double)t)/CLOCKS_PER_SEC;
printf("The command ");
inputted_command(argc,argv);
if(WIFSIGNALED(status)){
printf("is interrupted by the signal number = %d (Insert Name Here) real: %.2f, user: , system: , context switch: \n",WTERMSIG(status),real_time_taken);
}
else{
printf("terminated with return status code = %d real: %.2f, user: , system: , context switch: \n",WEXITSTATUS(status), real_time_taken);
}
}
else if(pid==0){
childpid=getpid();
printf("Process with id: %d created for the command: ",(int)getpid());
inputted_command(argc,argv);
printf("\n");
assert(pid == 0);
if (handle_signals)
signal(SIGINT, SIG_DFL);
execvp(argv[1], &argv[1]);
printf(" experienced an error in starting the command: ");
inputted_command(argc,argv);
printf("\n");
exit(-1);
}
}
- A portion of my code has been commented which I'm unsure how to go about doing.
- My Idea here is to first let the Parent process go to sleep so the child process finishes terminating.
- Then the parent process creates a new child process to access the PROC/Fie system and get the necessary data(Which has been commented).
- Finally, I call the wait function again and terminate the initial child process
So my main question here is whether this would be an appropriate way to go about getting information for the child process and how do I go about getting the information(Mainly the System Time, User Time and the voluntary and involuntary context switches?
Here's a test program that I cooked up that may shed some light (Caveat: it is somewhat crude):
Here is the program output:
Without using
wait
, the parent can't know definitively/easily/cleanly because the alternate way to check for a live process (e.g.kill(pid,0)
) still returns 0. This was [somewhat] surprising to me.Based on the test program output, one way that might work is to do a
readlink
on/proc/pid/cwd
and check for error (i.e. error means process exited and is in zombie state).Another way is to read
/proc/pid/status
and look for:State: Z (zombie)
After the
wait
is done, even a pre-opened stream on/proc/pid/status
returns EOF. So, no joy.The man page does some other files that change when the process becomes zombie (e.g.
/proc/pid/cmdline
)With some impetus from Craig Estey's answer, following on from my comment, and using information from POSIX for
sigaction()
, which points to Signal Actions and<signal.h>
, I came up with the following code which usesSA_SIGINFO
handling for theSIGCHLD
signal, which allows the program to glean information from the/proc
file system for the child process after it has terminated but before it has been waited for.siginfo47.c
Some of this code is available in my SOQ (Stack Overflow Questions) repository on GitHub. Specifically, the files
stderr.c
andstderr.h
can be found in the src/libsoq sub-directory. They greatly simplify the error reporting.Example runs include:
As noted by the help message, the
exitcode
program dies with an exit status, either normally (exitcode 23
) or as a result of a signal (exitcode -s 13
).