/* */ /* Physics 673 Computer Assignment #2 */ /* Trevor Nickle */ /* November 20, 1996 */ /* */ /* Purpose */ /* */ /* To create a program that will spawn a secondary */ /* Process. Have this process terminate normally without*/ /* Having the calling process terminate before hand. */ /* Once the orignal process has determined that the */ /* Child process has terminated then terminate the */ /* Parent process. All zombie processes should be */ /* Included. */ /* */ /* Variables */ /* */ /* STAT Integer pointer that is used to satisfy the necessary */ /* Requirements of the waitpid routine. */ /* T Integer variable that stores the returned value from */ /* The fork routine. T = 0 inside the child and */ /* T = Child Process ID # inside the parent */ /* W Integer variable that stores the returned value from */ /* A waitpid routine. Equals process id if process is */ /* Alive. Equals -1 if process is dead. */ /* PARENT Integer value that stores the id of the parent */ /* CHILD Integer value that stores the id of the child */ /* PP Integer value that stores status of the parent pipe */ /* PC Integer value that stores status of the child pipe */ /* PIPEFD 2 Dimensional integer array that allows child to */ /* Talk to parent and parent to listen */ /* PIPEFD2 2 Dimensional integer array that allows parent to */ /* Talk to child and child to listen */ /* KID Character pointer that records child's thoughts */ /* MOM Character pointer that records parent's thoughts */ /* CHILDMSG Character array that stores child's actual message */ /* PARENTMSG Character array that stores parent's actual message */ /* BUF Integer that limits the length of message passed */ /* NUMPASSED Integer stores number of charcters passed over pipes*/ /* NUMREAD Integer stores number of characters read over pipes */ /* */ /* NOTICE THE ROUTINE STRNCPY IS USED TO PICK A PIECE OF A */ /* LARGER STRING AND PASS IT. THIS ENSURES THAT THE PIPE*/ /* IS ACTUALLY PASSING INFORMATION SEEING THAT BOTH THE */ /* ORIGINAL STRINGS ARE KNOWN TO BOTH PROCESSES. HENCE */ /* IT WOULD BE UNCLEAR WHETHER OR NOT THE PIPE ACTUALLY */ /* PASSED DATA WITHOUT USING SOME STRING MANIPULATION */ /* ROUTINE. */ #include#include #include #include #include #include #include #include #define BUF 13 #define MASK 0644 int main() { int myshmid; int ff,fd; int numpassed,numread; int *stat; int t,w,pp,pc,parent,child; int pipefd[2],pipefd2[2]; char *kid = "Hey Battle Axe!\0"; char *mom = "Well I Never! You Little Jerk!\0"; char *kid2= "Oops Sorry Mom.\0"; char *mom2= "That's Better My Child.\0"; char childmsg[BUF],parentmsg[BUF]; char childmsg2[BUF],parentmsg2[BUF]; char *stupid = "./dumb.file"; printf("PARENT: This Program Creates A Child\n"); printf(" \n"); parent = getpid(); printf("PARENT: The Parent Process Id is %d\n",parent); printf(" \n"); system("ps -l | grep a.out | grep -v grep"); /* Shows Parent is Alive */ printf(" \n"); printf("PARENT: A Child Will Now Be Born\n"); printf(" \n"); printf("PARENT: I remember the first words my child said to me\n"); printf("PARENT: They were intended to be %s\n",kid); printf("PARENT: But that wasn't said - What was? Find out soon!\n"); printf(" \n"); ff = mkfifo(stupid, MASK); printf("PARENT: ff is %d\n",ff); if (ff==-1) printf("PARENT: Waring! Fifo not created\n"); /* Above line checks to see that fifo created properly */ /* Infact it is this line that I spent all day yesterday */ /* trying to figure out. Do you know why it will return */ /* -1 most times and 0 maybe 1 in 30?? */ pp = pipe(pipefd); /* Generates two pipes with pp and pc being */ pc = pipe(pipefd2); /* The respective flags of each pipe */ printf("PARENT: pp = %d %d %d\n",pp,pipefd[0],pipefd[1]); printf("PARENT: pc = %d %d %d\n",pc,pipefd[0],pipefd[1]); if ((pp<0)||(pc<0)) { /* Error Checking for pipe creation */ printf("PARENT: Error in creating pipes\n"); exit(1); } printf("PARENT: stupid is %s\n",stupid); /* Above line checks that data file is known to process */ printf("PARENT: Both pipes are successfully created\n"); printf(" \n"); t = fork(); /* Child process is spawned here */ if (t<0) { /* Error checking for successful fork execution */ printf("PARENT: Miscarriage\n"); exit(1); } if (t==0) { /* Child process executes only this part of the if */ /******************/ /* Part 2A */ /* */ printf("CHILD: Child Born\n"); printf("CHILD: Here I am!\n"); printf(" \n"); printf("CHILD: Sending Info To Mom\n"); printf("CHILD: My Message is %s\n",strncpy(childmsg,kid,(BUF-3))); numpassed = write(pipefd[1],childmsg,(int)strlen(strncpy(childmsg,kid,(BUF-3)))); /* Above write statement tells parent child's thougths - 1st 10 */ /* Characters of the "kid" message */ close(pipefd[1]); /* Closes Pipe for writing to parent */ printf("CHILD: PIPE CLOSED FOR WRITING TO PARENT\n"); printf("CHILD: numpassed is %d\n",numpassed); if (numpassed==-1) { /* Error Check for writing to pipe */ printf("CHILD: Write Error!\n"); exit(1); } sleep(5); printf(" \n"); printf("CHILD: I wonder what mom will say to that?\n"); numread = read(pipefd2[0],childmsg,BUF); /* Reads from parent */ close(pipefd2[0]); /* Closes pipe for reading from parent */ printf("CHILD: PIPECLOSED FOR READING FROM PARENT\n"); if (numread==-1) { /* Error check for reading from pipe */ printf("CHILD: I didn't hear you Mom!\n"); exit(1); } printf("CHILD: Mom's Reply - %s\n",childmsg); /* */ /* Part 2A Ends */ /****************/ /* Part 2B */ /* */ sleep(10); printf("CHILD: Entering part 2b\n"); fd = open(stupid,O_RDWR,0); printf("CHILD: fd = %d\n",fd); if (fd==-1) { printf("CHILD: Open statement incorrect #1\n"); /*exit(1);*/ } printf("CHILD: My Message is %s\n",strncpy(childmsg2,kid2,(BUF-3))); numpassed = write(fd,childmsg2,(int)strlen(strncpy(childmsg2,kid2,(BUF-3)))); close(fd); printf("CHILD: Numpassed is %d\n",numpassed); sleep(3); printf("CHILD: Waiting for parents reply\n"); fd = open(stupid,O_RDWR,0); printf("CHILD: fd = %d\n",fd); if (fd==-1) { printf("Open statement incorrect #2\n"); /*exit(1);*/ } numread = read(fd,childmsg2,(BUF-3)); /* Reads from parent */ close(fd); printf("CHILD: Closed fifo for reading\n"); if (numread==-1) { printf("CHILD: Error in read #3\n"); /*exit(1); */ } printf("CHILD: Parent's message is %s\n",childmsg); /* */ /* Part 2B Ends */ /****************/ /* Part 1 */ /* */ sleep(1); printf(" \n"); child = getpid(); printf("CHILD: My Process ID is %d\n",child); printf(" \n"); system("ps -l | grep a.out | grep -v grep"); /* Shows Parent & Child */ printf(" \n"); /* Alive and well */ printf("CHILD: Life Sucks - I'm Going To Die Now\n"); } /* Child executions end here. Child becomes a Zombie */ /* */ /* Part 1 Ends */ /****************/ else { /* Parent Executes Only This Part of the code */ /****************/ /* Part 2A */ /* */ printf(" \n"); numread = read(pipefd[0],parentmsg,(BUF-3)); /* Reads from child */ printf("PARENT: numread = %d\n",numread); close(pipefd[0]); /* Closes pipe for reading from child */ printf("PARENT: PIPE CLOSED FOR READING FROM CHILD\n"); if (numread==-1) { /* Error Check for reading from pipe */ printf("PARENT: Read Error!\n"); exit(1); } printf("PARENT: What did my darling child say to me? %s\n",parentmsg); printf(" \n"); printf("PARENT: This kid is mine???\n"); printf("PARENT: %s - No better not say that.\n",mom); printf("PARENT: Instead... \n"); printf("PARENT: %s\n",strncpy(parentmsg,mom,BUF)); numpassed=write(pipefd2[1],parentmsg,(int)strlen(strncpy(parentmsg,mom,BUF))); /* Above write sends message to child */ close(pipefd2[1]); /* Closes pipe for writing to child */ printf("PARENT: PIPE CLOSED FOR WRITING TO CHILD\n"); printf("PARENT: Number passed is %d\n",numpassed); sleep(10); /* */ /* Part 2A Ends */ /****************/ /* Part 2B */ /* */ sleep(10); printf(" \n"); printf("PARENT: What did the child say this time?\n"); fd = open(stupid,O_RDWR,0); if (fd==-1) { printf("PARENT: Open Error #4\n"); /*exit(1);*/ } numread = read(fd,parentmsg2,(BUF-3)); /* Reads from child */ /* The above line needs to be commented out for the program to */ /* run to completion and see the zombie process */ close(fd); printf("PARENT: Read to fifo closed\n"); printf("PARENT: Numread is %d\n",numread); printf("PARENT: Child's reply %s\n",parentmsg2); printf("PARENT: Well this is what I think\n"); fd = open(stupid,O_RDWR,0); if (fd==-1) { printf("PARENT: Open error #5\n"); /*exit(1);*/ } printf("PARENT: My message is %s\n",strncpy(parentmsg2,kid2,(BUF-3))); numpassed = write(fd,parentmsg2,(int)strlen(strncpy(parentmsg2,kid2,(BUF-3)))); close(fd); printf("PARENT: Numpassed is %d\n",numpassed); if (numpassed==-1) { printf("PARENT: Error in writing #6\n"); /*exit(1);*/ } /* */ /* Part 2B Ends */ /****************/ /* Part 1 */ /* */ sleep(3); printf(" \n"); system("ps -l | grep a.out | grep -v grep"); /* Shows Zombie Process */ printf(" \n"); printf("PARENT: Child Process %d Is A Zombie!\n",t); w = waitpid(t,stat,1); while (w!=-1) { /* This While confirms that the child has died */ /* printf("w is %d\n",w);*/ w = waitpid(t,stat,1); } /* Once parent is here, child is dead and removed */ /* Parent is now allowed to terminate */ printf(" \n"); printf("PARENT: Lets See What My Child Is Up To?\n"); printf(" \n"); system("ps -l | grep a.out | grep -v grep"); /* Shows only parent proc */ printf(" \n"); printf("PARENT: Child Process %d Is Dead And Removed - Time To Exit\n",t); printf(" \n"); } /* */ /* Part 1 Ends */ /****************/ return 0; }