Process Management



What is a process:
Process is a program under execution.
Program is a set of instructions and is a static entity but process is a dynamic entity. It is born, it is run for some time and then it is terminated. Process comprises of not only the instructions and data, it also has CPU registers, stack and program counter. Linux is a multi tasking operating system and so at any point of time, there will many processes being run.

Try this:
ps shell command displays list of all running processes for your terminal,
ps –a
displays all the processes running


States of a process:

A process can be in any of the following states.


Running
Ready to Run
Sleeping
Stopped
Zombie


When a process is created, it is in ready to run state. At any point of time, there will be many processes ready to run and hence waiting for CPU’s attention.
When a process is scheduled, it is in the running state. In a uni-core (one CPU) architecture, only one process will be running at any point of time.
The running process is put to sleep, either when it waits for an event or when its time quantum is over. The sleeping process is woken up when the event happens
If a running process receives a stop signal, it goes to stop state
When a process is terminated, it releases all its resources and becomes a zombie.

Process descriptor
The context of a process is stored in process descriptor. In Linux, this structure is called task_struct. This structure stores the informations like beginning of code, data and stack, open file descriptors, parent and child process pointers, signal handlers, pending signals, pending alarms, file system details etc. It also stores one important field – process identifier or pid.
Process id
PID is a 16 bit unique identifier of a process. When a process is created, it is allocated with next available pid. When pid reaches maximum value normally 32767, the unused pids are again used.

int getpid()
returns pid of the current process
int getppid()
returns parent pid of the process


Process Destruction
A process dies normally when it calls return or exit or abnormally when it receives some fatal signal. When a process dies, all its resources are released except for its process descriptor. Now it becomes a zombie process.
The process descriptor is retained because, the parent may want to know the exit status of the child process. When the parent gives a wait4 system call, parent obtains the exit status and also removes the process descriptor.

What if the parent dies without calling wait system call?
In this situation, the process is adapted by init process, which periodically calls wait system call.
Spawning a process
Unix and Linux, create a process using 2 step procedure, First fork() system call is used to create a copy of the current process, then exec system call is used to execute another process in child.

fork(): System call creates a new process. The existing process is called parent and new process is called child.
Child process inherits address space, open file descriptors, file system information, signal handlers etc. But it does not share any of the resources.
Child will get a new pid and will be ready to run. It is the child process which will be executed first.
Child will be the exact copy of parent process and will execute all the instructions parent process. Only way to differentiate between the two is by the return value of fork. Fork returns 0 when child process is being executed and returns child’s pid when parent is being executed.
Linux also uses copy on write (COW) mechanism for address space in order to improve efficiency.





#include
#include
int main()
{
pid_t p1;
p1 = fork();
printf(“p1=%d\n”,p1);
}

Output:
P1 =0
P1=1876


Let us try to analyze this program. This program creates the child process using fork. After fork is called, the subsequent statements are executed twice, by the parent and by the child. Hence the program prints p1 two times.

The child process inherits all resources of parent and shares none of the resources. Child will get its own address space, file descriptors, signal handlers etc.

The actual copying of the address space is delayed using copy on write mechanism. When the child is created the pages are all marked as read only. When either child or parent tries to modify them, that page is copied to child process.



Note that all the processes except for init (process 1) are created using fork so they all have a parent processes.
Execing a process
When a process calls exec family system call, another program is run under current process. The address spaces of the current process is overwritten by the new program. The old process is no longer present.
But now the new process is inheriting pid and ppid of the old process. And also it inherits the pending signals, and pending alarms and file locks.

Syntax
int execl(char *path, …);
int execv(char *path,char *argv[])
execl is used when the command line arguments are given as list of strings terminated by NULL. Execv is used when command line arguments have to be given as array of character pointers with NULL pointer as last element

#include

#include

int main()
{

printf(“My pid is ”,getpid());
if (execl(“/bin/ps”,”ps”,”-el”,NULL)<0)

perror(“exec error”);

printf(“bye\n”);

}

Output: P1 =0 P1=1876

The program prints its pid . then calls execl to execute the ps program. Ps program runs with same pid as the original program. Normally fork and exec are combined together. Child is created using fork and child will call exec to run new program and parent will continue with original program. Exercise : Write a program to edit a c file and then compile it and finally execute it.

Comments

Popular Posts