Transcript The Process
The Process
CIS 370, Fall 2009
CIS UMassD
The notion of a process
In UNIX a process is an instance of a
program in execution
A job or a task
Each process has program code, data
segment, program stack etc.
The shell (or any command interpreter)
starts a process for each command
submitted.
Process examples
$ cat file1 file2
results in the shell creating a process
specifically for running this command
$ ls | wc
results in the shell creating two processes where
the output of ls is sent (via the pipe) as in input
to wc
Processes are different from programs
a single program may create several processes.
How to create a process
UNIX provides several mechanisms for
creating processes.
fork - creates a new process by duplicating the
calling process.
exec - perform the transformation of a process
by overlaying its memory space with a new
program.
wait - provides the ability for a process to be
halted while a related process finishes.
exit - used to terminate a process.
The fork system call
Usage :
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
A successful call will result in the creation of a
new process that is more or less identical to the
calling process.
The Process
The newly created process is called as the
child process and the process that made
the call is called as the parent process.
After the system call is made successfully
both processes begin execution at the
statement after the call to fork.
Both processes will have identical data and
code segments. All the variable will have
the same value as before the fork call.
OUTPUT
printf(“one\n”);
pid = fork();
printf(“two\n”);
PC
PC
fork()
$ one
$ two
$ two
Before
After
printf(“one\n”);
pid = fork();
printf(“two\n”);
PC
printf(“one\n”);
pid = fork();
printf(“two\n”);
PC
Process IDs
fork() returns two values, unlike most
system calls.
fork() returns the process id of the newly
created process to the parent.
fork() returns a 0 to the newly created
process.
Since all the variables are common, this
can be used to synchronize and distinguish
the child process from the parent process.
The exec family of calls
• Unlike fork, exec will replace the calling
process.
• fork replicates the calling process, exec
will create a new process and destroys the
called process. The new process will
inherit the process id of the called
process.
• What is the point? What is interesting
about simply the same process over and
over again?
printf (…)
PC
execl(“bin/ls”,…)
PC
Before
exec
After
1st line of ls
PC
Data and File Sharing in fork
• In fork(), an identical copy of the parent
process is made.
• All the variables are identical and all files
open in the parent will remain open in the
child process.
• Since the child process occupies a different
memory location, modifications are local.
• Open files are are however different. The
read-write pointer is maintained by the OS.
Data and File Sharing in exec
• Open file descriptors are also passed across
exec calls.
• The read-write pointer remains in the same
position as in the process that called exec.
• What about variables and their values?
• The system call fcntl can be used to set the
close-on-exec flag. When this flag is set
the file is closed when the exec calls is
made.
#include<fcntl.h>
int fd;
fd = open(“file”, O_RDONLY);
.
/* set close-on-exec flag on */
fcntl(fd, F_SETFD, 1);
/*set close-on-exec flag off */
fcntl (fd, F_SETFD, 0);
/* the value can be obtained as follows */
res = fcntl(fd, F_GETFD, 0);
Terminating a process - exit
• Usage
#include < stdlib.h>
void exit(int status);
Synchronizing Processes - the
wait system call
• Usage
#include<sys/types.h>
#include<sys/wait.h>
pid_t wait (int *status);
wait() temporarily suspends the process till
its child process finishes execution.
More on wait
• The call to wait returns the process id of
the child process that exits
• The argument to wait is an integer pointer
that contains the exit code of the exiting
child process.
• If there are n child processes, n wait
statements would be needed if the parent is
to continue after all the child processes
have exited.
Waiting for a specific child
• Usage
#include<sys/types.h>
#include<sys/wait.h>
pid_t waitpid(pid_t pid, int *status, int options);
• The first argument specifies the id of the
process the parent is waiting for (if this is
set to -1 and the options to 0, this call
behaves exactly like wait() ).
waitpid system call
• The second argument contains the exit
status of the child.
• The final argument options can take a
variety of values defined in <sys/wait.h>
• The most useful is the option WNOHANG
• This allows waitpid to sit in a loop,
without blocking.
• waitpid returns the process id of the child
process once terminated.
Zombies and premature exits
• A process becomes a zombie when a child
process exits before the parent process
issues a wait.
• This results in the process occupying space
in the system’s process table but nothing
else.
• If a parent process exits before a child
process is done. That process is
“orphaned” and is “adopted” by the OS
(and killed!).
The shell - What it shall do
• Assemble commands and execute them
• Execute in either foreground or
background (command used with &).
• Deal with a line with multiple commands
separated by semicolons.
• I/O redirection (< >) and pipe (|) will be
added later (by you!)
A small Shell program
• A shell is a command interpreter.
• The idea is simple
while( EOF not typed)
{
get command line from user
assemble command args and execute
wait for child
}
Lets define some useful constants
The userin function
• The userin.c will get the command line.
• The program will print a prompt, then
wait for a line of input from the keyboard.
• Any input (read one character at a time) it
receives will be placed in a buffer.
• We shall set a max length for the command
line, the program will also check for any
violations.
The userin.c program
The gettok.c program
• This program extracts individual tokens
from the command line constructed by
userin.
• A token is a lexical unit such as a
command name or argument.
• gettok is invoked as follows:
• toktype = gettok(&tptr);
• toktype is an integer indicating the type of
token, defined in smallsh.h.
gettok.c continued
• tptr is a character pointer that points to the
actual token itself after the call to gettok.
• Note that since it references the character
pointers tok and ptr, it must be included in
the same source file as userin.
• This is why tok and ptr are initialized as
they are in userin.
inarg is used to determine whether a character
can be part of an ‘ordinary’ argument. For the
time being, we need just check whether the
character is special to smallsh or not:
Procline.c program
• procline will parse a command line using
gettok, constructing an argument list in the
process.
• When it encounters a newline or semicolon
it invokes a routine called called
runcommand to execute the command.
• It assumes that an input has already been
read with userin.
runcommand.c
• The next stage is the runcommand function
that actually starts any command
processes.
• The runcommand is very similar to the
docommand seen earlier, except it takes
an additional parameter (where) to indicate
if the process is to be run in foreground or
background.
• The waitpid is also omitted (we’ll see
why).
Now the main function that ties all
these together.