I have a homework question that asks me to get 2 integers from the user, put them in shared memory, fork a child, have the child add them and put the result in shared memory, and then the child will end and the parent will print out the sum. The program must also loop until the user does CTRL+C, at which point it should catch the signal and the parent should detach and remove shared memory, SIGKILL
the child, and then terminate itself.
I've already submitted this, and it got full credit, but I can't help but feel there is a better way. Mainly, my concern is with the way I free the memory at the bottom of main()
and, how I handle the signal. I really wanted to free the memory in the signal handler, but couldn't figure out how to do that without making all the shared variables globals. Those if (runFlag
) statements don't seem particularly elegant to me either.
#define _POSIX_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
int runFlag = 1; //this flag will be set to 0 by a SIGINT
/* This function creates a shared memory area in the parent's address space of size size_of_shared_memory, and returns a void* pointer to it */
void *create_shared_memory(int size_of_shared_memory){
int fd;
void *area;
fd = open("/dev/zero", O_RDWR);
area = mmap(0, size_of_shared_memory, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
return area;
}
void intHandler()
{//toggle runFlag so main loop exits
runFlag = 0;
//shmdt(); //detaches shared memory
//shmctl(shm_id, IPC_RMID, NULL); //removes shared memory
return;
}
int main(int argc, char **argv)
{
int *num1 = (int *)create_shared_memory(sizeof(int));
int *num2 = (int *)create_shared_memory(sizeof(int));
int *sum = (int *)create_shared_memory(sizeof(int));
int *flag = (int *)create_shared_memory(sizeof(int));
*flag = 1;
int child_pid;
while(runFlag)
{//runFlag will be changed by a SIGINT
//since runFlag could be changed anywhere we must test for it whereever the program will be sitting
if (runFlag) printf("\nEnter the first number: ");
if (runFlag) scanf("%d", num1);
if (runFlag) printf("Enter the second number: ");
if (runFlag) scanf("%d", num2);
if (runFlag)
{
*flag = 1;
child_pid = fork();
signal(SIGINT, intHandler);
if(child_pid < 0){
printf("Fork error. \n");
exit(-1);
}
if(child_pid == 0){ // Child code
signal(SIGINT, SIG_IGN); //ignore ctrl+c
*sum = *num1 + *num2;
*flag = 0; //signal to parent that child is done
exit(0);
}
/* Parent code */
while (*flag); //wait for child to signal it is done
/* Read the integers from shared memory */
printf("The sum is: %d\n", *sum);
}
}
//exit
printf("\n");
munmap(num1, sizeof(int)); //unmap memory
munmap(num2, sizeof(int));
munmap(sum, sizeof(int));
munmap(flag, sizeof(int));
if (child_pid > 0) kill(child_pid, SIGKILL); //kill child process
exit(0); //kill parent
}