CS 3733 Operating Systems Notes: USP Chapter 3



fork:

   #include <sys/types.h>
   #include <unistd.h>

   pid_t fork(void);
return -1 if error
return 0 to child
return child's pid to parent

Example 3.5, page 65: What is the value of x for each process
Example 3.6, Page 65: Parent and child print different messages
Program 3.1, Page 67: a chain of processes, parent always breaks
Program 3.2, Page 68: a fan of processes, the child breaks


Problem from Spring 2001 Final Exam:
Trace the following program segment and determine how many processes are created. Assume that no errors occur. Draw a graph that shows how the processes are related. In this graph each process will be represented by a small circle containing a number that represents which fork created the process. The original process will contain 0 and the process created by the first fork will contain 1. There will be arrows from each parent to all of its children. Each arrow should point in a downward direction.

   c2 = 0;
   c1 = fork();      /* fork number 1 */
   if (c1 == 0)
      c2 = fork();   /* fork number 2 */
   fork();           /* fork number 3 */
   if (c2 > 0)
      fork();        /* fork number 4 */


wait:

   #include <sys/wait.h>

   pid_t wait(int *stat_loc);
   pid_t waitpid(pid_t pid, int *stat_loc, int options);
wait:
If a child terminated, return its pid
Otherwise return -1 and set errno

waitpid:
Allows you to wait for a particular process, or all process if pid is -1. Important option is NOHANG which will return 0 if there is a specified child to wait for but it has not yet terminated.

Important values of errno:
ECHILD no unwaited for children
EINTR a signal was caught

The status value is 0 if and only if the process terminated normally and returned 0. In all other cases the status should be examined using the provided macros defined in sys/wait.h.

Program 3.3 shows how to restart a wait call when it is interrupted by a signal.
Exercise 3.20, the parent waits for all of its children
Exercise 3.21, each process waits for its child.

The following code segments waits for all children that have finished but does not block if there are no children whose status is available:

   pid_t childpid;

   while (childpid = waitpid(-1, NULL, WNOHANG))
      if ((childpid == -1) && (errno != EINTR))
         break;

Status values
The following macros are available for checking the return status of a child:

   #include <sys/wait.h>

   WIFEXITED(int stat_val)
   WEXITSTATUS(int stat_val)
   WIFSIGNALED(int stat_val)
   WTERMSIG(int stat_val)
   WIFSTOPPED(int stat_val)
   WSTOPSIG(int stat_val)
They are used in pairs.
If WIFEXITED returns true, the child executed normally and the return status (at most 8 bits) can be gotten with WEXITSTATUS.

The other ones are used when the process exits because of a signal or is stopped.
Example 3.22 on page 77 gives an example of using these.


exec

   #include <unistd.h>

   extern char **environ;
   int execl(const char *path, const char *arg0, ... /*, char *(0) */);
   int execle (const char *path, const char *arg0, ... /*, char *(0),
               char *const envp[] */);
   int execlp (const char *file, const char *arg0, ... /*, char *(0) */);
   int execv(const char *path, char *const argv[]);
   int execve (const char *path, char *const argv[], char *const envp[]);
   int execvp (const char *file, char *const argv[]);
The execl forms take a variable number of parameters with a NULL-terminated list of command line arguments.
The execv forms take an argv array which can be created with makeargv.

The p forms use the PATH environment variable to search for the executable.
The e forms allow you to set the environment of the new process rather than inheriting it from the calling process.

Program 3.4 creates a child to run ls -l.
Program 3.5 creates a child process to execute a command given on the command line.
Program 3.6 creates a child process to execute a command given as a single string on the command line.

Many of the attributes of a program are inherited after an exec.
These include the processID, the userID (owner), current working directory, and open file descriptors.