Forks
fork: a system call that creates a new process
under the UNIX operating system
Crucial warning:
For CS330 Labs,
you ABSOLUTELY MUST use a linux machine instead of hercules
for any program containing a fork() system call.
This requirement is due to the possibility of a fork bomb ,
which is a runaway process that creates too many other processes
either directly or indirectly.
At present, the CC compiler does not run on linux. Use g++
instead. The g++ on linux is good.
For example, if a program contains a call to fork( ), the execution
of the program results in the execution of two processes.
One process is created to start executing the program.
When the fork( ) system call is executed, another process is
created. The original process is called the parent process and the second
process is called the child process. The child process is an almost
exact copy of the parent process. Both processes continue executing
from the point where the fork( ) calls returns execution to the
main program. Since UNIX is a time-shared
operating system, the two processes can execute concurrently.
Click here to see a sample program testing some system calls
Click here to see a sample program without fork
Click here to see the output
Click here to see a sample program with fork that runs two processes forever
Click here to see the output
Click here to see a sample program with fork that prints 5 lines each from
two processes
Click here to see the output
- fork2.cpp program creates two processes, as does fork3.cpp
- The value returned by fork( ) is stored in a variable of type pid_t,
which is really an integer. Since the value of this variable is not used,
we could have ignored the result of fork(), i.e., type cast it to void
- With fork2.cpp, each process keeps printing its process id (pid) over and over again
- You have to kill these processes with control-c
- For documentation on fork( ), see
man 2 fork
- To find out the id of a process, the getpid( ) system call is used
- For documentation on getpid( ), see
man 2 getpid
Some differences between the child and parent process are:
- different pids
- in the parent, fork( ) returns the pid of the child process
if a child process is created
- in the child, fork( ) always returns 0
- separate copies of all data,
including variables with their current values
and the stack
- separate program counter (PC) indicating where to
execute next; originally
both have the same value but they are thereafter separate
- after fork, the two processes do not share variables
fork returns:
- the pid of the new child process: to the parent process;
this is equivalent to telling the parent the name of its child.
- 0: to the child process
- -1: 1 if there is an error; i.e., fork( ) failed because a new process
could not be created
wait:
- a system call that causes the process to wait for a signal
(waits until any type of signal is received from any process).
- most commonly used in a parent process to wait for the signal
that the OS sends to a parent when its child is terminated
- returns the pid of the process sending the signal
- see
man 2 wait
for documentation
Suppose we want to have the parent wait for a signal from
the child process:
Click here to see a sample program
Click here to see the output
-
In this simple example, the parent waits for the child to finish.
-
The parent process enters a do/while loop. When it receives a
signal, it checks the wait_result, which tells it which process
sent the signal. If it is equal to the child's pid, the
parent can terminate. Otherwise, it waits for another signal.
execl:
Suppose we want the new process to do something quite different
from the parent process, namely run a different program. The execl system call loads a new executable into memory and associates it with the
current process. In other words, it changes things so that
this process starts executing executable code from a different file.
- In the following program, execl is called to load the
file /bin/ls into memory. The argument vector is set to
the words "ls" and "-l".
- argv[0] is set to "ls"
- argv[1] is set to "-l"
- The number of arguments to execl can vary so we end
with NULL to show that there are no more arguments.
Click here to see a sample program with fork/exec and wait
that executes the system program named ls, using the executable
file called /bin/ls and using one parameter "-l". The overall
result is equivalent to doing: ls -l
Click here to see a sample program with fork/exec and wait
Click here to see the output
process control block (pcb):
data structure in OS that represents one process
Fork Bombs
- You are ABSOLUTELY FORBIDDEN to experiment with programs
involving fork on hercules.
- Why? Because almost every term, some CS330 student crashes hercules
with a fork bomb, often at a crucial time for other classes.
- So test, your programs involving forks on a Linux workstation
- Below is a program with a loop that creates
2^n processes for n iterations through the loop. I have restricted
n to 4 or less (16 processes or less)
- If argv[1] is 1, we get 2 processes, if it is 2, we get 4 processes,
if it is 3, we get 8 processes, and if it is 4, we get 16 processes.
- The danger is that inadvertantly, when experimenting with fork,
you will set up a process that creates a child process, and then both
of these processes will create child processes, and then all of these
processes will create child processes, and so on until the system
is overwhelmed. These processes are hard for the system manager to
kill because they keep creating more processes whenever resources
are available.
- Such a program is called a fork bomb.
- On the other hand, it is fine for you to experiment with fork
on the Linux machines. These Linux machines have names like "a035178",
whereas hercules has the name "hercules".
Click here to see a sample forkbomb program, restricted to n <= 4
Click here to see the output
To help understand the forkbomb, consider this series of simple
programs, which create 2^0 = 1, 2^1 = 2, 2^2 = 4, and 2^3 = 8
because they have 0, 1, 2, and 3 fork system calls, respectively.
simplefork0.cpp - no fork system call
simplefork1.cpp - one fork system call
simplefork2.cpp - two fork system calls
simplefork3.cpp - three fork system calls
Click here to see the output for all these programs
Implementation of the fork() system call:
- In UNIX, fork is a system call that creates a new pcb
- copies most information from the current process's pcb
into the next free location in the process table
- The parent and child processes will now both be ready to execute.
- One can be left/placed in the RUNNING state and the other in
the READY state.
- Henceforth, both will takes turns in using the processor (along
with all other processes).
- Which one is chosen to run first, depends on the exact version
of the operating system.
- In Windows, the CreateProcess system call
creates a new process initialized
to default/null entries, but in UNIX the entries are copied from an
existing process, namely the parent process.
Table of Contents