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 tomalloc/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.
4. 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