Assignment 10, due Apr 18

Solutions

Part of the homework for 22C:112, Spring 2008
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

  1. Background: The Unix fork() system call returns the process ID of the new process to the parent, and it returns zero to the child. The Unix exit() system call terminates a process with the indicated exit status. The Unix wait() system call blocks the caller until a child process terminates and then returns the process ID of the child. Further details can be found in the Unix programmer's reference manual (man 2 and in some cases man 3). There is also a waitpid() system call that waits for a specific child process to terminate.

    A problem: Write Unix code to do the actions A to J in the order given below:

          A
        /   \
      B       C
     / \     / \
    D   E   F   G
     \ /     \ /
      H       I
        \   /
          J
    

    Note that D and E must be completed before H, and F and G must be completed before I. The order ABDEHCFGIJ would be legal, as would ABCDEFGHIJ and ACGFIBEDHJ. This will take 3 forks and 3 waits, but it is important for the parent process to wait for specific children at the right time, and if some child terminates in an unexpected order, it is important for the parent to remember that this child has already terminated. (1.0 points).

    pid_t ida;
    A;
    ida = fork()
    if (ida) { /* parent */
            pid_t idb;
            B;
            idb = fork()
            if (idb) { /* parent */
                    pid_t idc;
                    D;
                    do { /* wait for the correct child to exit */
                            idc = wait( NULL );
                            if (idc == ida) ida = 0;
                    } while (idc != idb);
            } else { /* child */
                    E;
                    exit( EXIT_SUCCESS );
            }
            H;
            if (ida != 0) { /* ida may have already exited */
                    (void) wait( NULL );
            }
    } else { /* child */
            C;
            if (fork()) { /* parent */
                    F;
                    (void) wait( NULL );
            } else { /* child */
                    G;
                    exit( EXIT_SUCCESS );
            }
            I;
    }
    J;
    

  2. Background: The unix pipe(f) system call returns an array of two file descriptors, such that any data written on f[1] can later be read from f[0]. The pipe is really a FIFO bounded buffer with a capacity of around one disk sector, although the actual capacity is not documented. Pipes exist for the specific purpose of interprocess communication, so the normal way to use them is to create a pipe before a fork, and then have the resulting processes communicate through the pipe.

    a) Augment the following code so that statements B and C can communicate through a pipe. Specifically, statement B produces data that statement C consumes. Make sure you close any unneeded ends of the pipe, and make sure that all evidence of the pipe has been closed by the time the two logical threads of computation join:

    if (fork()) { /* parent */
            B;
            wait();
    } else { /* child */
            C;
            exit();
    }
    
    (1 point)
    {
            int mypipe[2];
            pipe( mypipe );
            if (fork()) { /* parent */
                    close( mypipe[WRITEEND] );
                    B;
                    close( mypipe[READEND] );
                    (void) wait( NULL );
            } else { /* child */
                    close( mypipe[READEND] );
                    C;
                    close( mypipe[WRITEEND] );
                    exit( EXIT_SUCCESS );
            }
    }
    

    b) Pipes were never intended for other purposes, but they can be abused in some interesting ways. Consider using a pipe as a semaphore, with the number of characters of data in the pipe used to indicate the count in the semaphore. Give implementations of the wait and signal operations using a pipe as the semaphore representaiton. (1 point)