LIP Unit IV.ppt
Unit IV
Process
Process
- A process is the execution of a program
- A process is consists of text (machine code),
data and stack
- Many process can run simultaneously as kernel schedules them for execution
- Several processes may be instances of one program
- A process reads and writes its data and stack
sections, but it cannot read or write the data
and stack of other processes • A process communicates with other processes
and the rest of the world via system calls
• Kernel has a process table that keeps
tract of all active processes- Each entry in the process table contains pointers to the text, data, stack and the U Area of a process.
- All processes in UNIX system, except the very first process (process 0)
which is created by the system boot
code, are created by the fork system call
Kernel Support for Process UNIX Process Data Structure Text Stack Data
File Descriptor Table Per Process Region Table Kernel Process Table
Kernel Region Table A Process U Area
Data Structure of Parent & Child Processes after Fork U Area U Area stack data text stack data Kernel File Kernel Region Parent Child Region table Region table
- When a process is created by fork, it contains
duplicated copies of text, data & stack segment of its parent.
- Also it has a file descriptor table that contains references to opened file by its parent.
- Along with this, process is assigned following attributes which are inherited by parent or set by
- Root Directory kernel.
- Signal Handling>Real User Identification Number (rUID)
- Signal Mask>Real Group Identification Number (rGID)
- Umask>Effective User Identification Number (eUID)
- Effective Group Identification Number (eGID)>Nice Value
- Process Group Identification Number (PGID)
- Controlling
- Current Directory
Device
- In addition to these attributes are different between parent & child processes
- Alarm Clock
- Process Identification Number (PID)>File Locks
- Parent Process Identification Number (PPID)
- Pending Signals
Process APIs
fork, vfork
- The fork system call is used to create a child process. The function prototype is
#include <sys/types.h> pid_t fork( void );
- The call succeeds. A child process is created and the function returns child process ID to the parent. The child process receives a zero return value from fork.
- The call fails. No child process is created and function sets errno with error code & returns -1.
- The common errors are ENOMEM (Insufficient Memory) and EAGAIN (No of processes exceed system imposed limit, try again later).
#include <iostream.h> #include <stdio.h> #include <unistd.h> int main() { pid_t child_pid;
cout<<“PID:”<<getpid()<<“, Parent:”<<getppid();
switch(child_pid=fork()) { case (pid_t)-1 : perror(“Fork”); break; case (pid_t)0 : cout<<“Child Created: PID” <<getpid()<<“Parent:”<<getppid()<<endl; exit(0); default : cout<<“Parent after fork. PID :”<<getpid() <<“Child PID: “ <<child_pid<<endl; } return 0; }- An alternative API is vfork with same prototype
#include <sys/types.h> pid_t vfork( void );
- The vfork() function is the same as fork() except that it does not make a copy of the address space.
- The memory is shared reducing the overhead of spawning a new process with a unique copy of all the memory.
- This is typically used when using fork() to exec() a process and terminate.
- The vfork() function also executes the child process first and resumes the parent process
when the child process calls exec or terminates
by calling _exit.
_exit
- The _exit system call terminates a process.
• This API will cause calling process data segment,
stack segment and U area to be deallocated and all open file descriptors to be closed.- The process table slot entry for this process is
still intact so that the process exit status and its
execution status are recorded therein. • The process is now called zombie process, as it
can no longer scheduled to run.- A zombie process or defunct process is a process that has completed execution but still has an entry in the process table. This entry is still needed to allow the parent process to read its child's exit status.
• An orphan process is a computer
process whose parent process has
finished or terminated, though it remains running itself.- The data stored in process table entry can be retrieved by the parent process using wait or waitpid system call.
#include<unistd.h> void _exit (int exit_code);
wait, waitpid
• The parent process will often want to wait
until all child processes have been completed/terminated.- This can be implemented with the wait() waitpid() function call.
- These call will deallocate Process Table
slot of the child process. The prototypes
are #include<sys/wait.h> pid_t wait (int *status_p); pid_t waitpid (pid_t child_pid, int - status_p, int options);
- wait: Blocks calling process until a signal is sent to the process or the child process
terminates or is stopped. If child process has
already terminated, the wait call returns immediately. - If the calling process has multiple child processes, the function returns when one returns.
- waitpid: this is more general than wait.
• Options available to block calling process for a
particular child process not the first one by specying one of the following values for the child_pid argument.
- If pid is equal to -1, status is requested for any child process. In this respect, waitpid() is equivalent to wait().
- If pid is greater than 0, it specifies the process ID of a single child process for which status is requested.
- If pid is 0, status is requested for any child
process whose process group ID is equal to
that of the calling process. • If pid is less than -1, status is requested for
any child process whose process group ID is equal to the absolute value of pid.
- status_p specifies the location to which the child process' exit status is stored. If NULL is passed, no exit status is returned. Otherwise, the following macros defined in <sys/wait.h> can be used to evaluate the returned status:
- WIFEXITED(status_p) : Returns a nonzero value if child was terminated via _exit otherwise zero.
- WEXITSTATUS(status_p) Returns a child exit code that was assigned to an _exit call
- WIFSIGNALED(status_p) Returns a nonzero value if a child was terminated due to signal interruption.
- WTERMSIG(status_p) If the value of WIFSIGNALED(s) is non-zero, this macro evaluates to the number of the signal that caused the termination of the child process.
- WIFSTOPPED(status_p) Evaluates to a non-zero
value if status was returned for a child process that is
currently stopped. - WSTOPSIG(status_p) If the value
of WIFSTOPPED(s) is non-zero, this macro evaluates
to the number of the signal that caused the child process to stop. - options is the bitwise OR of zero or more of the following flags, defined in <sys/wait.h>:
• WNOHANG The waitpid() function does not suspend
execution of the calling thread if status is notimmediately available for one of the child processes
specified by pid.- WNOTRACED The status of any child processes
specified by pid that are stopped, and whose status
has not yet been reported since they stopped, is also
- If waitpid() was invoked with WNOHANG set in options, and there are children specified by pid for which status is not available, waitpid() returns 0.
- If WNOHANG was not set, waitpid() returns the process ID of a child when the status of that child is available.
- Otherwise, it returns -1 and sets errno to one of the following values:
- – ECHILD The process or process group specified by pid does not exist or is not a child of the calling process.
- – EFAULT stat_loc is not a writable address.
- – EINTR The function was interrupted by a signal. The value of the location pointed to by stat_loc is undefined.
- – EINVAL The options argument is not valid.
exec
- The exec family of functions will change calling process context and initiate a program from within a program.
- There are six versions of exec system call. They have same function but they differ from each other in their argument.
- The exec family of functions creates a new process image from a regular, executable file. This file is either an executable object file, or an interpreter script.
- There is no return from a successful call to an exec() function, because the calling process is functionally replaced by the new process.
- The exec() functions only return if an error has have occurred. The return value is -1, and errno is set to
- The prototypes of exec functions are
#include <unistd.h>
int execl(const char *path, const char*arg,
...); int execlp(const char *file, const char*arg, …); int execle(const char *path, const char *arg, …, const char** env); int execv(const char *path, const char** argv,…); int execvp(const char *file, const char** argv, …); int execve(const char *path, const char** argv, …, const char**env);- The first argument to the function is either path name or file name of a
program to be executed, this should be
an executable file or shell script(excelp & execvp). - If call succeeds, the calling process instruction and data memory are overloaded with new program instruction text & data.
- When a new program completes execution, the process is terminated & exit code will be send to its parent process.
PARAMETERS
- path Specifies the path name of the new process image file.
- file Is used to construct a path name that identifies the new process image file. If it contains a slash character, the argument is used as the path name for this file. Otherwise, the path prefix for this file is obtained by a search of the directories in the environment variable PATH.
- arg0, ..., argn Point to null-terminated character strings. These strings constitute the argument list for the new process image. The list is terminated by a NULL pointer.
- The argument arg0 should point to a file name that is associated with the process being started by the exec() function.
- argv is the argument list for the new process image. This should contain an array of pointers to character strings, and the array should be terminated by a NULL pointer. The value in argv[0] should point to a file name that is associated with the process being started by the exec() function.
• envp Specifies the environment for the new
process image. This should contain an array of pointers to character strings, and the array should be terminated by a NULL pointer.
- The const char *arg and subsequent ellipses in the
execl(), execlp(), and execle() functions can be
thought of as arg0, arg1, ..., argn.- Together they describe a list of one or more pointers to null-terminated strings that represent the argument list available to the executed program.
- The first argument, by convention, should point to the filename associated with the file being executed.
- The list of arguments must be terminated by a
NULL pointer, and, since these are variadic functions ( variadic function is a function of indefinite arity, i.e., one which accepts a variable number of arguments), this pointer must be cast
- The execv(), execvp(), and execvpe()
functions provide an array of pointers to null- terminated strings that represent the argument list available to the new program.
• The first argument should point to the filename
associated with the file being executed.- The array of pointers must be terminated by a NULL pointer.
- The execle() and execvpe() functions allow the caller to specify the environment of the executed program via the argument envp.
- The envp argument is an array of pointers to null-terminated strings and must be terminated by a NULL pointer.
#include <unistd.h> //common to all programs main() { execl("/bin/ls", "/bin/ls", "-r", "-t", "-l",
(char *) 0); // (char *) 0 can be replace with NULL } main() {
char *args[] = {"/bin/ls", "-r", "-t", "-l", (char
- ) 0 };
execv("/bin/ls", args); } main() { execlp(“ls", “ls", "-r", "-t", "-l", NULL); } main() {
char *const parmList[] = {"/bin/ls", "-l", "/u/
userid/dirname", NULL}; char *const envParms[2] = {"STEPLIB=SASC.V6.LINKLIB", NULL};execve("/u/userid/bin/newShell", parmList,
envParms); }
system
- The system call will execute an OS shell command as described by a character command string.
- This function is implemented using fork, exec and waitpid.
- The command string is executed by calling /bin/sh -c command-string.
- Example #include <stdio.h> #include <stdlib.h> main() { system("ls -l"); printf("Command done!"); }
Signals
- Signals are sometimes called “software interrupts”.
- Signals are triggered by events and are posted on a process to notify it that something has happened and requires some action.
- For ex:- divide-by-zero, <Delete> or <Ctrl-C> key, etc.
- A signal is an asynchronous event which is delivered to a process.
- Asynchronous means that the event can occur at any time. The process does not know ahead of time exactly when a signal will occur.
- Signal can be sent by one process to another process (or to itself) or by the kernel to a process.
- may be unrelated to the execution of the process e.g. user types ctrl-C, or the modem hangs.
Signals are defined as integer flags, and the <signal.h> header depicts the list of signals defined for UNIX. The table below lists the POSIX defined signals.
Core File Signal Use genera Name ted at default
Alarm timer time-out. Generated by alarm( SIGALRM
No ) API. Abort process execution. Generated by
SIGABRT Yes abort( ) API.
SIGFPE Illegal mathematical operation.
Yes SIGHUP Controlling terminal hang-up.
No SIGILL Execution of an illegal machine instruction. Yes Process interruption. Can be generated by
SIGINT No <Delete> or <ctrl_C> keys.
Core File Signal
Use genera Name ted at default
Segmentation fault. generated by de- SIGSEGV
Yes referencing a NULL pointer. process termination. Can be generated by
SIGTERM Yes “kill <process_id>” command.
SIGUSR1 Reserved to be defined by user.
No SIGUSR2 Reserved to be defined by user. No Sent to a parent process when its child
SIGCHLD No process has terminated.
SIGCONT Resume execution of a stopped process.
No SIGSTOP Stop a process execution. No Stop a background process when it tries to
SIGTTIN No read from from its controlling terminal.
Stop a process execution by the control_Z
Sources for Generating Signals
- Hardware - A process attempts to access addresses outside its own address space.
- Divides by zero.
- Other Processes - A child process notifying its parent process that it has terminated.
- User - Pressing keyboard sequences that generate a quit, interrupt or stop signal.
Handling Signals
• When a signal is sent to a process, it is pending
on the process to handle it.- Process that receives a signal can take one of three action:
- Perform the system-specified default for the signal
- notify the parent process that it is terminating;
- generate a core file
(a file containing the current memory image of the
process) - terminate. - Catch the Signal :- When a process catches a signal, except SIGSTOP and SIGKILL, it invokes a special signal handing routine.
signal API
- All UNIX systems and ANSI-C support the signal API, which can be used to define the per-signal handling method.
- The prototype of the signal API is
void (*signal(int signo, void(*handler)(int) ) ) (int);
- Or in simple format
#include <signal.h> typedef void sighandler_t(int); sighandler_t *signal( int signo, sighandler_t *handler ); signal returns a pointer to a function that returns an int (i.e. it returns a pointer to sighandler_t)
- RETURN VALUE :- The signal() function returns
previous value of the signal handler, or SIG_ERR on
error.
Signal Handling
- Use the signal handling library: signal.h
- Then can use the signal call:
#include <signal.h> void (*signal( int sig, void (*handler)(int))) (int) ;
• signal returns a pointer to the PREVIOUS signal
handler
- #include <signal.h>
typedef void Sigfunc(int); Sigfunc * signal ( int signo, Sigfunc *handler ); Signal is a function that takes two arguments: sig and handler The signal to be caught or ignored is given as argument sig The function to be called when the specified signal is received is given as a pointer to the function handler The handler function Receives a single integer Argument and returns void The signal function itself returns a pointer to a function. The return type is the same as the function that is passed in, i.e., a function that takes an int and returns a void The returned function takes a integer parameter.
Signal Mask - sigprocmask API
- Each process has a system mask that defines which signals are blocked when generated to a process.
- A blocked signal depends on the recipient process to unblock it and handle it accordingly.
- A process initially inherits the parent’s signal mask when it is created, but any pending signals for the parent process are not passed on.
- A process can query or set its signal mask via sigprocmask API. #include<signal.h>
int sigprocmask ( int cmd, cost sigset_t
- *new_mask, sigset_t *old_mask); • The return value is zero if it succeeds or -1 if it fails.
- new_mask: defines a set of signals to be set or reset
in a calling process signal mask. new_mask = NULL, current process signal mask unaltered.
- cmd: specifies how the new_mask value is to be used:
- SIG_SETMASK: Overrides the calling process signal mask with the value specified in the new_mask argument.
- SIG_BLOCK: Adds the signals specified in the new_mask argument to the calling process signal mask.
- SIG_UNBLOCK: Removes the signals specified in the new_mask argument from the calling process signal mask
- old_mask: Address of a sigset_t variable that will be assigned the calling processing’s original signal mask. old_mask = NULL, no previous signal mask will be return.
The BSD UNIX & POSIX.1 define a set of API known as sigsetops functions, which set, reset and query the presence of signals in a sigset_t typed variable
- int sigemptyset (sigset_t* sigmask); Clears all signal flags in the sigmask argument.
- int sigaddset (sigset_t* sigmask, const int signal_num);
Sets the flag corresponding to the signal_num signal in the
sigmask argument. - int sigdelset (sigset_t* sigmask, const int signal_num); Clears the flag corresponding to the signal_num signal in the sigmask argument.
- int sigfillset(sigset_t* sigmask); Sets all the signal flags in the sigmask argument.
These functions returns zero if call succeed, -1 if they fails.
- int sigismember(const sigset_t* sigmask,const int signal_num); Returns 1 if the flag corresponding to the signal_num signal in the sigmask argument is set; zero if it is not set; -1 if call
/*get current signal mask*/ { perror(“sigprocmask”); exit(1); } else sigaddset(&sigmask, SIGINT); /* set SIGINT
flag*/
sigdelset(&sigmask, SIGSEGV); /* clear SIGSEGV flag
- */
if (sigprocmask(SIG_SETMASK,&sigmask,0) == -1) perror(“sigprocmask”); /* set a new signal mask */ }
sigpending API
- The sigpending API can find out whether one or more signals are pending for a process and set up special signal handing methods for those signals before the process calls the sigprocmask API to unblock them. # Include<signal.h> int sigpending (sigset_t* sigmask);
• sigmask argument, to the sigpending API, is
the address of a sigset_t-type variable and is assigned the set of signals pending for the calling process by the API.- The API returns 0 on Success; -1 on Failure and sets errno.
/* This program reports whether the SIGTERM signal is pending for the process. */ int main ( ) { sigset_t sigmask; sigemptyset(&sigmask); /* initialize set */ if (sigpending(&sigmask) == -1)
/* Any signal is pending */ perror(“sigpending”); else cout<<”SIGTERM signal is:” <<
(sigismember (&sigmask,SIGTERM) ? “Set” : “No
Set”); }sigaction API
• The sigaction API is a replacement for the signal API in latest UNIX & POSIX systems.
- The sigaction API setups a signal handling method
for each signal it wants to deal with and passes back the previous signal handling method for a given signal.
- The sigaction API blocks the signal it is catching
allowing a process to specify additional signals to be blocked when the API is handling a signal. include<signal.h> int sigaction ( int signal_num, struct sigaction* action, struct sigaction* old_action);
- The API returns 0 on Success, -1 on Failure and sets errno.
- sa_handler is the function point of a user- defined signal handler function, SIG_IGN (ignores a signal), or SIG_DFL (accepts the default action of a signal).
- sa_mask specifies additional signals that a
process wishes to block when it is handling the
signal_num signal. - sa_flag specifies special handling for certain signals.
The values for sa_flag are as follows
0:when the signal_num is SIGCHLD, the kernel will send the
SIGCHLD signal to the calling process whenever its child
process is either terminated or stopped.SA_NOCLDSTOP: when the signal_num is SIGCHLD, the kernel will generate the SIGCHLD signal to the calling
process whenever its child process is either terminated,
but not when the child process has been stopped.
SA_RESETHAND: If signal_num is caught, the sa_handler is
set to SIG_DFL before the signal handler function is called, and signal_num will not be added to the process signal maskSA_RESTART: If a signal is caught while a process is executing a system call, the kernel will restart the system
call after the signal handler returns. If this flag is not set
in the sa_flag, after the signal handler returns, the systemcall will be aborted with a return value of -1 and will set
errno to EINTR (aborted due to a signal interruption).Arguments of sigaction -
sigaction (4)