Agenda for Today
Review of previous lecture
Process creation and termination
Process management in UNIX/Linux— system
calls: fork, exec, wait, exit
Sample codes
Recap of the lecture
Process Creation
Reasons to create processes are as follows:
User request for process creation
Created by OS to provide a service
Spawned by existing process
Process Creation
In process spawning the running process called
parent process creates other processes which are
known as children processes. These children
processes in turn create other processes, forming
a tree of processes.
Resource sharing
Parent and children share all resources.
Parent and child share no resources.
Execution
Parent and children execute concurrently.
Parent waits until children terminate.
Process Creation …
Address space
Child duplicate of parent.
Child has a program loaded onto it.
UNIX examples
fork system call creates a new process
exec system call used after a fork to replace the
process’ memory image with a new executable.
Processes Tree on a UNIX
System
fork()
When the fork system call is executed, a new
process is created which consists of a copy of the
address space of the parent.
The return code for fork is zero for the child process
and the process identifier of child is returned to the
parent process.
On success, both processes continue execution at
the instruction after the fork call.
On failure, -1 is returned to the parent process and
errno is set appropriately to indicate the reason of
failure; no child is created
What’s Happening at Process Creation?
The OS:
◦ Assigns a unique process identifier
◦ Allocates space for the process
◦ Initializes process control block
fork()—Sample Code
main()
{
int pid; Parent Process pid = 1234
...
pid = fork();
if (pid == 0) {
Child Process pid = 0
/* Code for child */
...
}
else {
/* Code for parent */
...
} Kernel Space
...
}
fork()—Inherits from the
Parent
The child process inherits the following attributes
from the parent:
Memory
Stack
Current working directory
Root directory
Open file descriptor table
Signal handling settings
Nice value
Etc.
fork()—Child Differs from
the Parent
The child process differs from the parent process:
Different process ID (PID)
Different parent process ID (PPID)
Child has its own copy of parent’s file descriptors
Etc.
fork()—Reasons for Failure
Maximum number of processes allowed to
execute under one user has exceeded
Maximum number of processes allowed on the
system has exceeded
Not enough swap space
Process Termination
Process executes the last statement and requests
the operating system to terminate it (exit).
Output data from child to parent (via wait).
Process resources are deallocated by the
operating system, to be recycled later.
Process Termination …
Parent may terminate execution of children
processes (abort).
Child has exceeded allocated resources (main
memory, execution time, etc.).
Parent needs to create another child but has
reached its maximum children limit
Task performed by the child is no longer
required.
wait()
The wait system call suspends the calling process
until one of its immediate children terminates, or
until a child that is being traced stops because it
has hit an event of interest.
wait returns prematurely if a signal is received. If all
children processes stopped or terminated prior to
the call on wait, return is immediate.
wait() ...
If the call is successful, the process ID of the
terminating child is returned.
If parent terminates all its children have assigned
as their new parent, the init process. Thus the
children still have a parent to collect their status
and execution statistics.
wait() ...
Zombie process—a process that has terminated
but whose exit status has not yet been received by
its parent process or by init.
Sample Code—fork
#include <stdio.h>
void main()
{
int pid, status;
pid = fork();
if(pid == -1) {
printf(“fork failed\n”);
exit(1);
}
Sample Code—fork
if(pid == 0) { /* Child */
printf(“Child here!\n”);
exit(0);
}
else { /* Parent */
wait(&status);
printf(“Well done kid!\n”);
exit(0);
}
}
Semantics of fork
fork
P
exec()
Typically the exec system call is used after a fork
system call by one of the two processes to replace
the process’ memory space with a new executable
program.
There can be no return from a successful exec
because the calling process image is overlaid by
the new process image
Sample Code—fork and exec
#include <stdio.h>
void main()
{
int pid, status;
pid = fork();
if(pid == -1) {
printf(“fork failed\n”);
exit(1);
}
Sample Code—fork and
exec
if(pid == 0) { /* Child */
if (execlp(“/bin/ls”, “ls”, NULL)< 0) {
printf(“exec failed\n”);
exit(1);
}
}
else { /* Parent */
wait(&status);
printf(“Well done kid!\n”);
exit(0);
}
}
Semantics of fork
parent parent parent
P P P
fork
P P ls ls
exec
child child child
1 2 3