Vous êtes sur la page 1sur 23

Linux process control with C

Process in linux

A process is defined as an “instance” of an


executing program.

Any time a user executes a command at a


command line, a Linux process is created.

Every process on a Linux system has a unique


PID. Users and programs use this PID to
communicate with other processes.

Key command to find out various processes


and their properties on a Linux system is ps.
Process types

Interactive process : initialized and controlled


through terminal session. They are not started
automatically as part of system function. These
process can run in foreground and background. Job
control feature of Linux can be used to switch a task
between foreground and background.

Automatic process: they are not connected to a


terminal, they are queued into a spooler area where
they wait to be executed on a FIFO basis.

Daemons: server process that run continuously.


Mostly they are started at system startup and wait in
background until their service is required. e.g. netid
Process creation phases

The three important phases of creation of


processes in Linux are as follows:
Fork

Exec

wait

FORK

Forking creates a process by creating a copy of


the existing process.

The new process has a different PID and the


process that created it becomes its parent.

Otherwise the parent and the child have the


same process image.

If the child does not do an exec, both parent


and child would continue to execute the same
code from the time forking was invoked.
EXEC

Forking creates a process but it is not enough


to run a new program.

To do that, a fork child need to overwrite its


own image with the code and data of its own
program.

This mechanism is called exec and child


process is said to exec a new program.

No new process is created here and the PID


and PPID remain same for child and parent
process remain unchanged.
WAIT

While the child is executing a new program,


the parent process normally waits for the child
process to die.

It picks the exit status of the child before it


does something else.
The shell creation method

When the system moves to multiuser mode, init forks and


execs a getty for every active communication port.

Each one of these gettys prints the login prompts on the


respective terminal and then goes off to sleep.

When a user attempts to log in, getty wakes up and fork execs
the login program to verify the login name and the password
enterd.

On successful login, login forks-execs the shell process.


Init goes off to sleep, waiting for the death of its children.
Other processes getty and login self extenguish by overlaying.

When user logs off his shell is killed and is intimated to init.
init getty shell
fork Fork-exec login Fork-exec
Zombie process

Zombie processes are the leftover bits of the dead processes


that haven’t been cleaned up properly by their parent process.

Since they are already dead, hence zombies are no processes


at all.

When a sub-process exits, its parent process is supposed to use


the ‘wait’ system call and collect the processes exit
information.

The sub-process exists as a zombie process until this happens.


However if the parent process isn’t programmed properly or


has a bug the never call ‘wait’, the zombie process remains
eternally waiting for its information to be collected.
Impact of zombies

Zombie persist until their parent process ends.


Then they are adopted by init and cleaned.


More number of zombies eat up space and


PIDs which are limited in Linux, so new
processes can’t be launched.
SIGNAL

Signals are mechanisms to communicate with


processes.

Linux supports 31 non real time signals each


identified by a number from 1 to 31 or simple
names.

For instance ‘SIGKILL’ or signal number 9 tells


the program that someone tries to kill it.

To handle a signal, one of the threads of the


program stops its execution and temporarily
switches to signal handler.

Each one of the signals can be in one of the


following three states:

We may have our own signal handler for our


signal

Signals may be handled by default signal


handler.

Signal may be ignored or blocked.


Creating a process in background

To run a job in background using &


Use ‘&’ operator after command

Syntax is ‘command &’


Example: ls *.doc &


Alternate method ctrl+z then bg


First suspend the process using ctrl+z

Next use the bg command to send the suspended


job to the background.


Handling processes in Linux using C
The kernel of OS assigns each process running in
memory a unique ID to distinguish it from other
running processes, called as process ID or PID.
A library function getpid() can be used to know
the PID.
When the execution of program comes to an
end, process stands terminated. Every time we
run a program a new process is created.
Display PID of current process
#include<stdio.h>
#include<sys/types.h>

int main( )
{
printf ( "Process ID = %d", getpid( ) ) ;
return 0;
}
Parent and Child process
From a running process we can create another process hence creating
a parent child relationship between the existing and newly created
process.
We can do this by a library function called fork().

# include <stdio.h>
# include <sys/types.h> Output :
int main( ) Before Forking
{ After Forking
printf ( "Before Forking\n" ) ; After Forking
fork( ) ;
printf ( "After Forking\n" ) ;
}

Fork creates a child process and duplicates the


code of the parent process in the child
process. Thus duplicates the output.

When control returns from fork of the parent


process, it returns PID of the child process.

When control returns from fork() of the child


process, it always returns a zero.

We can use this functionality to segregate the


code that we want to execute by parent
process or child process.
# include <stdio.h>
# include <sys/types.h>
#include < unistd.h>
int main( )
{
int pid ;
pid = fork( ) ;
if ( pid == 0 )
{
printf ( "In child process\n" ) ;
/* code to play animated GIF file */
}
else
{
printf ( "In parent process\n" ) ;
/* code to copy file */
}
}
# include <unistd.h>
# include <sys/types.h>
# include <stdio.h>
int main( )
{
int pid ;
pid = fork( ) ;
if ( pid == 0 )
{
printf ( "Child : Hello I am the child process\n" ) ;
printf ( "Child : Child’s PID: %d\n", getpid( ) ) ;
printf ( "Child : Parent’s PID: %d\n”, getppid( ) ) ;
}
else
{
printf ( "Parent : Hello I am the parent process\n" ) ;
printf ( "Parent : Parent’s PID: %d\n”, getpid( ) ) ;
printf ( "Parent : Child’s PID: %d\n", pid ) ;
}
}
Exec family
To execute a process as part of the child process,
we first create a child process using fork() and then
we should call an exec() function to execute the
program on the disk.
exec family of functions are used as under:
execl() function permits us to pass a list of command
line arguments to the program.
Execv() does the same job except that command line
arguments are passes to it in form of array of pointers to
strings.
#include <stdio.h>
# include <unistd.h>
int main( )
{
int pid ;
pid = fork( ) ;
if ( pid == 0 )
{
execl ( "/bin/ls","-al", "/etc", NULL ) ;
printf ( "Child: After exec( )\n") ;
}
else
printf ( "Parent process\n" ) ;
}

After forking the child process, we have called the execl()


function.

This function accepts variable number of arguments.


The first parameter is absolute path


The remaining parameters describe the command-line


arguments for program to be executed.

The last parameter is end of parameter marker which always is


NULL.

Finally the command hence created is :


Ls –al /etc

As a result, all contents of the /etc directory are listed on the


screen

Also note that printf () will not be executed since execl() function
overwrites the image of the calling process with the code and
data of the program to be executed.

Vous aimerez peut-être aussi