Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h>
static struct itimerval real, virt, prof;
static int real_sec = 0, virt_sec = 0, prof_sec = 0;
/**************************************************
* Function prototypes
**************************************************/
long unsigned int fibonacci (unsigned int n);
static void handler_real(int sig);
static void handler_virt(int sig);
static void handler_prof(int sig);
void settimers(struct itimerval *r, struct itimerval *v, struct itimerval *p);
void gettimers(struct itimerval *r, struct itimerval *v, struct itimerval *p);
int main(int argc, char *argv[])
{
if (argc!=2)
{
fprintf(stderr,"Usage : %s fibonacci_number\n",argv[0]);
exit(0);
}
pid_t pid1, pid2;
struct sigaction sa_real, sa_virt, sa_prof;
static struct itimerval rt, vt, pt;
/*****************************************
* SA_RESTART flag is set to avoid
* Interrupted System call (EINTR) error.
*****************************************/
sa_real.sa_handler = handler_real;
sigemptyset(&sa_real.sa_mask);
sa_real.sa_flags = SA_RESTART;
sa_virt.sa_handler = handler_virt;
sigemptyset(&sa_virt.sa_mask);
sa_virt.sa_flags = SA_RESTART;
sa_prof.sa_handler = handler_prof;
sigemptyset(&sa_prof.sa_mask);
sa_prof.sa_flags = SA_RESTART;
if (sigaction(SIGALRM,&sa_real,NULL)<0)
{
perror("real : sigaction");
exit(1);
}
if (sigaction(SIGVTALRM,&sa_virt,NULL)<0)
{
perror("virt : sigaction");
exit(1);
}
if (sigaction(SIGPROF,&sa_prof,NULL)<0)
{
perror("prof : sigaction");
exit(1);
}
/*******************************************
* Set timer expiration to 1 second.
*******************************************/
real.it_value.tv_sec = 1;
real.it_value.tv_usec = 0;
virt.it_value.tv_sec = 1;
virt.it_value.tv_usec = 0;
prof.it_value.tv_sec = 1;
prof.it_value.tv_usec = 0;
pid1=fork();
if (pid1 == 0)
{
/************************************************
* First child process
************************************************/
settimers(&real,&virt,&prof);
fibonacci(atoi(argv[1]));
gettimers(&rt,&vt,&pt);
printf("Child1 : Real > %d sec %ld msec\n",real_sec,rt.it_value.tv_usec);
printf("Child1 : Virt > %d sec %ld msec\n",virt_sec,vt.it_value.tv_usec);
printf("Child1 : Prof > %d sec %ld msec\n",prof_sec,pt.it_value.tv_usec);
printf("\n");
fflush(stdout);
}
else if (pid1>0)
{
pid2=fork();
if (pid2==0)
{
/************************************************
* Second child process
************************************************/
settimers(&real,&virt,&prof);
fibonacci(atoi(argv[1]));
gettimers(&rt,&vt,&pt);
printf("Child2 : Real > %d sec %ld msec\n",real_sec,rt.it_value.tv_usec);
printf("Child2 : Virt > %d sec %ld msec\n",virt_sec,vt.it_value.tv_usec);
printf("Child2 : Prof > %d sec %ld msec\n",prof_sec,pt.it_value.tv_usec);
printf("\n");
fflush(stdout);
}
else if(pid2>0)
{
/************************************************
* Parent process
************************************************/
settimers(&real,&virt,&prof);
fibonacci(atoi(argv[1]));
gettimers(&rt,&vt,&pt);
printf("Parent : Real > %d sec %ld msec\n",real_sec,rt.it_value.tv_usec);
printf("Parent : Virt > %d sec %ld msec\n",virt_sec,vt.it_value.tv_usec);
printf("Parent : Prof > %d sec %ld msec\n",prof_sec,pt.it_value.tv_usec);
printf("\n");
fflush(stdout);
if (waitpid(pid1,NULL,WSTOPPED)<0)
perror("waitpid");
if (waitpid(pid2,NULL,WSTOPPED)<0)
perror("waitpid");
} else
perror("fork");
}
else
perror("fork");
return 0;
}
long unsigned int fibonacci (unsigned int n)
{
if (n==0)
return 0;
else if (n==1 || n==2)
return 1;
else
return (fibonacci(n-1)+fibonacci(n-2));
}
static void handler_real(int sig)
{
real_sec++;
if (setitimer(ITIMER_REAL,&real,0)<0)
{
perror("real : setitimer");
exit(1);
}
}
static void handler_virt(int sig)
{
virt_sec++;
if (setitimer(ITIMER_VIRTUAL,&virt,0)<0)
{
perror("virt : setitimer");
exit(1);
}
}
static void handler_prof(int sig)
{
prof_sec++;
if (setitimer(ITIMER_PROF,&prof,0)<0)
{
perror("prof : setitimer");
exit(1);
}
}
void settimers(struct itimerval *r, struct itimerval *v, struct itimerval *p)
{
if (setitimer(ITIMER_REAL,r,0)<0)
{
perror("real : setitimer");
exit(1);
}
if (setitimer(ITIMER_VIRTUAL,v,0)<0)
{
perror("virt : setitimer");
exit(1);
}
if (setitimer(ITIMER_PROF,p,0)<0)
{
perror("prof : setitimer");
exit(1);
}
}
void gettimers(struct itimerval *r, struct itimerval *v, struct itimerval *p)
{
if (getitimer(ITIMER_REAL,r)<0)
{
perror("getitimer");
exit(1);
}
if (getitimer(ITIMER_VIRTUAL,v)<0)
{
perror("getitimer");
exit(1);
}
if (getitimer(ITIMER_PROF,p)<0)
{
perror("getitimer");
exit(1);
}
}