Operating Systems - Projects and Exercises

Exercise 4 - Adding fork and exec To Your Shell

So far, our shell has used the system call to pass on command lines to the default system shell for execution. Since we need to control what open files and file descriptors are passed to these processes (i/o redirection), we need more control over there execution.

To do this we need to use the fork and exec system calls. fork creates a new process that is a clone of the existing one by just copying the existing one. The only thing that is different is that the new process has a new process ID and the return from the fork call is different in the two processes.

The exec system call reinitializes that process from a designated program; the program changes while the process remains!

Make sure you read the notes on fork and exec and understand how and why the forkexec.c example works before continuing.

Tutorial Exercises

  1. In your Shell program, replace the use of system with fork and exec.
     
  2. You will now need to more fully parse the incoming command line so that you can set up the argument array (char *argv[] in the above examples). N.B. remember to malloc/strdup and to free memory you no longer need!
     
  3. You will find that while a system function call only returns after the program has finished, the use of fork means that two processes are now running in foreground. In most cases you will not want your shell to ask for the next command until the child process has finished. This can be accomplished using the wait or waitpid functions. e.g.
switch (pid = fork ()) { 
   case -1:
      syserr("fork"); 
   case 0:                 // child 
      execvp (args[0], args); 
      syserr("exec");
   default:                // parent
      if (!dont_wait)
         waitpid(pid, &status, WUNTRACED);
 }  

Obviously, in the above example, if you wanted to run the child process 'in background', the flag dont_wait would be set and the shell would not wait for the child process to terminate.

  1. The commenting in the above examples is minimal. In the projects you will be expected to provide more descriptive commentry!

Code should be in 'straight' C using the compiler of your choice (cc or gcc).

Always use nice to execute your test programs at lower priority to ensure they do not inconvenience other users if they go 'haywire'. e.g.:
 
   >nice a.out

The descriptions of the system functions above are drawn from sources that include manuals on the Sun Solaris system and the MAC OS X Darwin/BDS system, and also from 'Advanced Programming in the UNIX Environment', W. Richard Stevens, Addison-Wesley, 1993.

Go home top

For use only by students and instructors using the supplementary material available with the text book: "Operating Systems - Internals and Design Principles", William Stallings, Prentice Hall, 5th Edition, 2004. Not to be printed out or copied by any other persons or used for any other purpose without written permission of the author(s).

©