/* file: simple_fork.c See comments and questions at the end of this file. */ #define _XOPEN_SOURCE 500 #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { int i = 0; int outfildes; char pathname[32]; FILE *outstream; pid_t child; if (argc <2) { fprintf (stdout, "Please enter a filename or pathname: "); if (!gets (pathname)) { /* use of gets() is very bad programming here -- Why? ==================== */ fprintf (stderr, "you must provide a filename\n"); exit (-1); } } else { strcpy (pathname, argv[1]); /* use of strcpy() is very bad programming here -- Why? ==================== */ } if ((outfildes = open (pathname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR)) == -1) { fprintf (stderr, "could not open file \"%s\" for writing: %s\n", pathname, strerror (errno)); exit (-2); } if (!(outstream = fdopen (outfildes, "w"))) { perror ("could not open stream for writing"); exit (-3); } while (i < 3) { if ((child = fork())) { /* this branch is executed only by the parent process */ fprintf (outstream, "i = %d in %d, who is the parent of %d\n", i, (int) getpid(), (int) child); /* the type cast (int) here is not may cause truncation, since int may be shorter than pid_t */ } else { /* this branch is only executed by the child process */ fprintf (outstream, "i = %d in %d, whose parent is %d\n", i, (int) getpid(), (int) getppid()); } i++; } fclose (outstream); close (outfildes); return 0; } /* Purpose: Demonstrate how to use the fork() system call and the use of ANSI C, as compared to C++. To compile this program: gcc -o simple_fork simple_fork.c To run this program, creating file "abc": ./simple_fork abc Sample contents of file "abc", when the above was done on a Linux machine with two CPU's: i = 0 in 14293, whose parent is 14292 i = 1 in 14296, whose parent is 14293 i = 2 in 14296, who is the parent of 14298 i = 0 in 14293, whose parent is 14292 i = 1 in 14296, whose parent is 14293 i = 2 in 14298, whose parent is 14296 i = 0 in 14293, whose parent is 14292 i = 1 in 14293, who is the parent of 14296 i = 2 in 14297, whose parent is 14293 i = 0 in 14292, who is the parent of 14293 i = 1 in 14292, who is the parent of 14294 i = 2 in 14295, whose parent is 14292 i = 0 in 14292, who is the parent of 14293 i = 1 in 14294, whose parent is 14292 i = 2 in 14299, whose parent is 14294 i = 0 in 14292, who is the parent of 14293 i = 1 in 14294, whose parent is 14292 i = 2 in 14294, who is the parent of 14299 i = 0 in 14293, whose parent is 14292 i = 1 in 14293, who is the parent of 14296 i = 2 in 14293, who is the parent of 14297 i = 0 in 14292, who is the parent of 14293 i = 1 in 14292, who is the parent of 14294 i = 2 in 14292, who is the parent of 14295 The actual order of output will vary, depending on how the processes are scheduled. Before the course is over, you should be able to answer all of the following questions: 1. How many new processes are created by running this program? 2. Can you explain why the file "abc" contains the information as shown above? In particular, why are there some duplicate lines? 3. What is the difference between a pathname and a filename? 4. What is the difference between stderr and stdout? 5. What happens if the user gives a pathname that is longer than 255 characters? 6. What determines the permission bits on the file that is created, if the file does not already exist? 7. What happens if the file already exists but the user does not have write permission for it? Why is that very bad? 8. What is the difference between a stream, an open file description, and an open file descriptor? Look at the man pages for the C library calls use here, including fprintf, strcpy, open, fdopen, perror, exit, getpid, getppid, fclose. If there is any detail of this program that you cannot figure out, ask questions, either in class, on the course discussion board, or by e-mail to one of the instructors for this course. */