Forking and Child Processes
Lab-4
Process Creation
In this lab, you will demonstrate your knowledge of process creation and manipulation.
You are required to write a C program (can just be main if you prefer) that uses fork,
execlp, and waitpidto create and control several processes. The program is to perform
the following tasks:
1. The program is to create three processes: the original process (parent) is to
create two child processes and one of those child processes is to create its own
child (i.e. a grandchild of the original (parent) process).
2. The original parent process is to wait until either one of its child processes
completes and then print the pid of the first process to complete. The original
parent process should then wait explicitly for the other child process and print a
message when it completes. The original parent process should then exit
normally.
3. The first child process should create another process and instead of
suspending itself, it should continually poll the child and sleep for 1 second. That
is, it should use the WNOHANG option of the waitpidsystem call. Each time it
polls, the process should printout that it will “Try again” after it executes a
sleep(1).
4. The grandchild (i.e. the child of the first child process) should sleep(3) and then
execute a “head -n 20 lab4.c” command to list the contents of the lab source
code. It should then exit(0). (Assuming your program name is lab4.c. If not
substitute your source code filename).
5. The second child process should read in the file
/home/COIS/3380/lab4_sourcefile and write out a local copy, called
lab4_file_copy, in the current directory. It should then print out the number of
bytes the file contained and then, exit(0). The output from this child should look
something like: –>Second child: 1317 bytes transferred.
6. Run the program again but put a sleep(5) in the second child process just before
the exit(0).
Change the indent level for each child or prefix each line with different
text. The output of the first run of your program should look something like:
-I am the first child
—-I am the grandchild
I’m the parent, first child has pid 21505
-I am the first child, grandchild has pid 21506
-Try again
–I am the second child
— –>Second child: 1317 bytes transferred.
I’m the parent again, second child has pid 21507
Parent – Child 21507 is done
-Try again
**** should see first 20 lines of lab4.c file here
Parent – Other child 21505 is done
The second run will see the first child complete first. The output would look something
like:
I am the first child
I am the grandchild
I am the first child, grandchild has pid 11045
Try again
I’m the parent, first child has pid 11044
I am the second child
I’m the parent again, second child has pid 11046
Try again
**** should see first 20 lines of lab4.c file here
Parent – Child 11044 is done
–>Second child: 1317 bytes transferred.
Parent – Other child 11046 is done
Solution
lab4.c
in // the terminal | is the path // for binary file of a linux system. //Replace it with the corresponding // command of your OS exit(0); //exit successfully } else { // This is the first child printf(“-I am the first child, grandchild has pid %ld\n”, (long)childID); while(1) { //poll the grandchild endID = waitpid(childID, &status, WNOHANG|WUNTRACED); //get the endID and status of grandchild if (endID == -1) { // error calling waitpidperror(“waitpid error”); exit(EXIT_FAILURE); } else if (endID == 0) { // grandchild still running printf(“-Try again\n”); sleep(1); //sleep for 1 unit } else if (endID == childID) { // grandchild ended if (WIFEXITED(status)) { printf(“-I am the first child, grandchild has pid %ld\n”, (long)endID); } exit(0); //exit successfully } } } } else if(i == 1){ // second child printf(“–I am the second child\n”); FILE *source, *target; // declared file pointers source = fopen(“./lab4.c”, “r”); // This is the source file name. Change the path according // to your need target = fopen(“./lab4_copy.c”, “w”); //This is the path of the new file to be created. Change // the path according to your need char ch; intcount_bytes = 0; // to count number of bytes. Each character has a size of 1 byte while( ( ch = fgetc(source) ) != EOF ){ // read the source file one character at a time count_bytes += 1; // keep on increasing the number of bytes read fputc(ch, target); // write the character in target file } fclose(source); // close source file fclose(target); // close target file printf(“– –>Second child: %d bytes transferred.\n”, count_bytes); // sleep(5); // Uncomment this line for Part-6 of the pdf. It asks to sleep the second child // for 5 units } exit(0); //exit } else{ // this is parent process if (i == 0){ // for child 1 printf(“I’m the parent, first child has pid %ld\n”, (long)pids[i]); } else if(i == 1){ // for child 2 printf(“I’m the parent again, second child has pid %ld\n”, (long)pids[i]); } } } /* Wait for children to exit. */ int status; // status of children pid_tpid; // to store pids of children while (n > 0) { pid = wait(&status); if(n == 2){ // first child to exit printf(“Parent – Child %ld is done\n”, (long)pid); } else if(n == 1){ // second child to exit printf(“Parent – Other child %ld is done\n”, (long)pid); } –n; // decrease the value of n } return 0; }
lab4_copy.c
in // the terminal | is the path // for binary file of a linux system. //Replace it with the corresponding // command of your OS exit(0); //exit successfully } else { // This is the first child printf(“-I am the first child, grandchild has pid %ld\n”, (long)childID); while(1) { //poll the grandchild endID = waitpid(childID, &status, WNOHANG|WUNTRACED); //get the endID and status of grandchild if (endID == -1) { // error calling waitpidperror(“waitpid error”); exit(EXIT_FAILURE); } else if (endID == 0) { // grandchild still running printf(“-Try again\n”); sleep(1); //sleep for 1 unit } else if (endID == childID) { // grandchild ended if (WIFEXITED(status)) { printf(“-I am the first child, grandchild has pid %ld\n”, (long)endID); } exit(0); //exit successfully } } } } else if(i == 1){ // second child printf(“–I am the second child\n”); FILE *source, *target; // declared file pointers source = fopen(“./lab4.c”, “r”); // This is the source file name. Change the path according // to your need target = fopen(“./lab4_copy.c”, “w”); //This is the path of the new file to be created. Change // the path according to your need char ch; intcount_bytes = 0; // to count number of bytes. Each character has a size of 1 byte while( ( ch = fgetc(source) ) != EOF ){ // read the source file one character at a time count_bytes += 1; // keep on increasing the number of bytes read fputc(ch, target); // write the character in target file } fclose(source); // close source file fclose(target); // close target file printf(“– –>Second child: %d bytes transferred.\n”, count_bytes); // sleep(5); // Uncomment this line for Part-6 of the pdf. It asks to sleep the second child // for 5 units } exit(0); //exit } else{ // this is parent process if (i == 0){ // for child 1 printf(“I’m the parent, first child has pid %ld\n”, (long)pids[i]); } else if(i == 1){ // for child 2 printf(“I’m the parent again, second child has pid %ld\n”, (long)pids[i]); } } } /* Wait for children to exit. */ int status; // status of children pid_tpid; // to store pids of children while (n > 0) { pid = wait(&status); if(n == 2){ // first child to exit printf(“Parent – Child %ld is done\n”, (long)pid); } else if(n == 1){ // second child to exit printf(“Parent – Other child %ld is done\n”, (long)pid); } –n; // decrease the value of n } return 0; }