You are on page 1of 47

PE-1 (Unix Programming Lab

Process

Sandeep Singh Rawat

Department of Computer Science & Engineering


Anurag University, Hyderabad, India

https://sites.google.com/view/sandeeprawat
Process - Concepts

Process
• Each instance of a running program constitutes a process.
• A Process consists of program code, data, variables (occupying system
memory), open files (file descriptors) and an environment.

Process Structure
• Each process is allocated a unique number, a process identifier, or PID. This is
usually a positive integer between 2 and 32768.

• Processes Share Memory area among themselves which is used to hold Program
code. Same way The system libraries can also be shared.
What are Not Shared
• Variables that it uses are distinct for each process. processes have their own set of file
descriptors used for file access.
• Process has its own stack space.
• Process must also maintain its own program counter.

The Process Table


• The UNIX process table is like a data structure describing all of the processes that
are currently loaded with, for example, their PID, status and command string.
Process, Process structure:
• Every process has a unique process ID, a non-negative integer. Unique, process IDs are
reused. As processes terminate, their IDs become candidates for reuse.
• Process ID 0 is usually the scheduler process and is often known as the swapper.
• Process ID 1 is usually the init process and is invoked by the kernel at the end of the bootstrap
procedure. The init process never dies.
• process ID 2 is the page daemon.
• In addition to the process ID, there are other identifiers for every process.
• The following functions return these identifiers.
#include <unistd.h>
pid_t getpid (void);
Returns: process ID of calling process.
pid_t getppid (void);
Returns: parent process ID of calling process.
uid_t getuid (void);
Returns: real user ID of calling process.
uid_t geteuid (void);
Returns: effective user ID of calling process
gid_t getgid (void);
Returns: real group ID of calling process.
gid_t getegid (void);
Returns: effective group ID of calling process.
• None of these functions has an error return.
Starting new process
Starting New Processes

• Process is started by another, known as its parent process. A process so started is known
as a child process.
• When UNIX starts, it runs a single program, the prime ancestor and process number 1,
init.
• We can cause a program to run from inside another program and thereby create a new
process by using the system library function.

#include <stdlib.h>
int system (const char *string);
Duplicating the Process
a process duplicate is created with fork ( ) function.
Replacing the Process Image.
A process image is replaced with another process by the exec( ) family functions.
Waiting for a Process
a parent process can wait for it’s child processes to complete execution with the help of
variations of wait( ) system calls.
Zombie process, process control
Zombie Processes
• A process which has finished the execution but still has entry in the process table to report
to its parent process is known as a zombie process.
• A child process always first becomes a zombie before being removed from the process
table.
• The parent process reads the exit status of the child process which reaps off the child
process entry from the process table.

How to spot a Zombie Process


$ps -elf | grep Z
// A C program to demonstrate Zombie Process.
// Child becomes Zombie as parent is sleeping
// when child process exits.
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// Fork returns process id
// in parent process
pid_t child_pid = fork();

// Parent process
if (child_pid > 0)
sleep(50);

// Child process
else
exit(0);

return 0;
}
Orphan Processes
• An orphan process is a computer process whose parent process has finished or
terminated, though it remains running itself.
• In a Unix-like operating system any orphaned process will be immediately adopted by the
special init system process.
• This operation is called re-parenting and occurs automatically. Even though technically the
process has the init process as its parent, it is still called an orphan process since the
process that originally created it no longer exists.

How to spot a Orphan Process


ps -elf | grep “process id or name”
// A C program to demonstrate Orphan Process.
// Parent process finishes execution while the
// child process is running. The child process
// becomes orphan.
#include<stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// Create a child process
int pid = fork();
if (pid > 0)
printf("in parent process");
// Note that pid is 0 in child process
// and negative if fork() fails
else if (pid == 0)
{
sleep(30);
printf("in child process");
}
return 0;
}
Process identifiers, fork, vfork, exit,
wait, exe
fork Function:
• An existing process can create a new one by calling the
fork function.
#include <unistd.h>
pid_t fork(void);
Returns: 0 in child, process ID of child in parent, -1 on error.
The new process created by fork is called the child process.
This function is called once but returns twice. The only
difference in the returns is that the return value in the
child is 0, whereas the return value in the parent is the
process ID of the new child.
Eg:
int glob = 6;
char buf[] = "a write to stdout\n";
int main(void)
{
int var; pid_t pid; var = 88;
if (write(STDOUT_FILENO, buf, sizeof (buf)-1) != sizeof (buf)-1)
err_sys("write error");
printf("before fork\n");
if ((pid = fork()) < 0)
{
err_sys("fork error");
}
else if (pid == 0)
{
glob++; var++;
}
else
{
sleep(2);
}
printf("pid = %d, glob = %d, var = %d\n", getpid(), glob,
var);
exit(0);
}
$ ./a.out
a write to stdout
before fork
pid = 430, glob = 7, var = 89
pid = 429, glob = 6, var = 88
uses for fork:
1.When a process wants to duplicate itself so that the
parent and child can each execute different sections of
code at the same time.
2.When a process wants to execute a different program.
This is common for shells.
vfork :
• The function vfork has the same calling sequence and
same return values as fork.
• The vfork function creates the new process, just like fork,
without copying the address space of the parent into the
child, as the child won't reference that address space.
• vfork guarantees that the child runs first, until the child
calls exec or exit. When the child calls either of these
functions, the parent resumes.
exit :
A process can terminate normally in five ways:
1.Executing a return from the main function.
2.Calling the exit function.
3.Calling the _exit or _Exit function.
4.Executing a return from the start routine of the last
thread in the process.
5.Calling the pthread_exit function from the last thread in
the process.
Once the process terminates, the kernel closes all the open
descriptors for the process, releases the memory that it
was using.
Exit Functions
Three functions terminate a program normally: _exit and
_Exit, which return to the kernel immediately, and exit,
which performs certain cleanup processing and then
returns to the kernel.
#include <stdlib.h>
void exit( int status);
void _Exit( int status);
#include <unistd.h>
void _exit( int status);
wait and waitpid Functions:
#include <sys/ wait.h>
pid_t wait(int *statloc);
pid_t waitpid( pid_t pid, int *statloc, int options);
Both return: process ID if OK, or -1 on error.
• The wait function can block the caller until a child process
terminates, whereas waitpid has an option that prevents it from
blocking.
• The waitpid function doesn't wait for the child that terminates first;
it has a number of options that control which process it waits for.
For both functions, the argument statloc is a pointer to an
integer. If this argument is not a null pointer, the
termination status of the terminated process is stored in
the location pointed to by the argument.
The interpretation of the pid argument for waitpid depends
on its value:
pid == 1 Waits for any child process.
pid > 0 Waits for the child whose process ID equals pid.
pid == 0 Waits for any child whose process group ID equals
that of the calling process.
pid < 1 Waits for any child whose process group ID equals
the absolute value of pid.
The options constants for waitpid:
WCONTINUED
WNOHANG
WUNTRACED
The waitpid function returns the process ID of the child that
terminated and stores the child's termination status in the
memory location pointed to by statloc.
exec Functions:
• Exec replaces the current process its text, data, heap, and
stack segments with a brand new program from disk.
• with the exec functions, we can initiate new programs.
There are six different exec functions.
#include <unistd.h>
int execl (const char *pathname, const char *arg0, ... /*
(char *)0 */ );
int execv (const char *pathname, char *const argv []);
int execle (const char *pathname, const char *arg0, ... /*
(char *)0, char *const envp[] */ );

int execve (const char *pathname, char *const argv[], char


*const envp []);

int execlp (const char *filename, const char *arg0, ... /* (char
*)0 */ );

int execvp (const char *filename, char *const argv []);


All six return: 1 on error, no return on success.
• The first difference in these functions is that the first four
take a pathname argument, whereas the last two take a
filename argument. When a filename argument is
specified
If filename contains a slash, it is taken as a pathname.
Otherwise, the executable file is searched for in the
directories specified by the PATH environment variable.
• The functions execl, execlp, and execle require each of the
command-line arguments to the new program to be
specified as separate arguments. We mark the end of the
arguments with a null pointer.

• For the other three functions (execv, execvp, and execve),


we have to build an array of pointers to the arguments,
and the address of this array is the argument to these
three functions.
PE-1 (Unix Programming)

Signals

Sandeep Singh Rawat

Department of Computer Science & Engineering


Anurag University, Hyderabad, India

https://sites.google.com/view/sandeeprawat
Signal functions, unreliable signals
Signals:
• Signals are software interrupts. Signals provide a way of handling asynchronous
events.
• Every signal has a name. These names all begin with the three characters SIG.
These names are all defined by positive integer constants (the signal number) in
the header <signal.h>.
• No signal has a signal number of 0.
The following table lists out common signals you might encounter and want to use in your
programs

Signal Name Signal Description


Number
Hang up detected on controlling terminal or death of
SIGHUP 1 controlling process
SIGINT 2 Issued if the user sends an interrupt signal (Ctrl + C)

SIGQUIT 3 Issued if the user sends a quit signal (Ctrl + D)


Issued if an illegal mathematical operation is attempted
SIGFPE 8

If a process gets this signal it must quit immediately and


SIGKILL 9 will not perform any clean-up operations

SIGALRM 14 Alarm clock signal (used for timers)


SIGTERM 15 Software termination signal (sent by kill by default)
Signal Function:
• The simplest interface to the signal features of the UNIX System is the signal
function.
include <signal.h>
void (*signal(int signo, void (*func)(int)))(int);
Returns: previous disposition of signal if OK, SIG_ERR on error.
• The signo argument is just the name of the signal.
• The value of func is (a) the constant SIG_IGN, (b) the constant SIG_DFL, or
(c) the address of a function to be called when the signal occurs.
Unreliable Signals:

Unreliable signals mean that signals could get lost: a signal


could occur and the process would never know about it.
Also, a process had little control over a signal: a process
could catch the signal or ignore it.
Interrupted system calls, kill, raise
functions
Interrupted System Calls:
• It is a system call within the kernel that is interrupted
when a signal is caught.
• To support this feature, the system calls are divided into
two categories: the "slow" system calls and all the others.
• The slow system calls are those that can block forever.
• Reads that can block the caller forever if data isn't present with
certain file types.
• Writes that can block the caller forever if the data can't be accepted
immediately by these same file types.
• Opens that block until some condition occurs on certain file types.
• The pause function and the wait function.
• Certain ioctl operations.
• Some of the interprocess communication functions .
kill and raise Functions:
• The kill function sends a signal to a process or a group of
processes.
• The raise function allows a process to send a signal to
itself.
#include <signal.h>
int kill( pid_t pid, int signo);
int raise(int signo);
Both return: 0 if OK,-1 on error.
There are four different conditions for the pid argument to
kill.
pid > 0 The signal is sent to the process whose process ID
is pid.
pid == 0 The signal is sent to all processes whose process
group ID equals the process group ID of the sender and
for which the sender has permission to send the signal.
pid < 0 The signal is sent to all processes whose process
group ID equals the absolute value of pid and for which
the sender has permission to send the signal.
pid == 1 The signal is sent to all processes on the system
for which the sender has permission to send the signal.

• The super user can send a signal to any process.


Alarm, pause, abort, system ,sleep
functions
alarm function:
• The alarm function allows us to set a timer that will expire
at a specified time in the future.
• When the timer expires, the SIGALRM signal is generated.
#include <unistd.h>
unsigned int alarm(unsigned int seconds);
Returns: 0 or number of seconds until previously set alarm.
The seconds value is no.of clock seconds in the future when
the signal should be generated.
• If, when we call alarm, a previously registered alarm clock
for the process has not yet expired, the number of
seconds left for that alarm clock is returned as the value
of this function.
• If a previously registered alarm clock for the process has
not yet expired and if the seconds value is 0, the previous
alarm clock is canceled. The number of seconds left for
that previous alarm clock is still returned as the value of
the function.
pause function:
• The pause function suspends the calling process until a
signal is caught.
#include <unistd.h>
int pause(void);
Returns: 1 with errno set to EINTR
• The only time pause returns is if a signal handler is
executed and that handler returns.

pause() causes the calling process (or thread) to sleep until a signal is delivered that either
terminates the process or causes the invocation of a signal-catching function.
abort Function:
• The abort function causes abnormal program termination.
#include <stdlib.h>
void abort(void);
This function never returns.
• This function sends the SIGABRT signal to the caller.
system Function:
• It is convenient to execute a command string from within
a program.
#include <stdlib.h>
int system(const char *cmdstring);
• If cmdstring is a null pointer, system returns nonzero only
if a command processor is available. This feature
determines whether the system function is supported on
a given operating system. Under the UNIX System,
system is always available.
The system is implemented by calling fork, exec, and
waitpid, there are three types of return values.
• If either the fork fails or waitpid returns an error ,system
returns 1 with errno set to indicate the error.
• If the exec fails, implying that the shell can't be executed,
the return value is as if the shell had executed exit(127).
• Otherwise, all three functions fork, exec, and waitpid
succeed, and the return value from system is the
termination status of the shell, in the format specified for
waitpid.
sleep Function:
#include <unistd.h>
unsigned int sleep(unsigned int seconds);
Returns: 0 or number of unslept seconds.
This function causes the calling process to be suspended
until either
• The amount of wall clock time specified by seconds has
elapsed. The return value is 0.
• A signal is caught by the process and the signal handler
returns. Return value is the number of unslept seconds.

You might also like