vfork system call
intended to create a new process when the purpose of the new process is to exec a new program , and it do so without fully copying the parent address space into the child.
no duplication of virtual memory pages is done for child process. child shares parent's address space until it either performs exec() or call exit().
Execution of parent process is suspended until the child has performed an exec() or an exit().
int main(){
pid_t cpid = vfork();
if (cpid == 0){
sleep(1);
printf("Hello I am child..\n");
sleep(2);
printf("Hello I am child again, I am exitting.\n");
sleep(2);
exit(0);
}
else{
printf("\nHello I am parent, my child has terminated\n");
exit(0);
}
}
notice paraent process is suspended until child process finishes.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int gvar = 54;
int main(){
int lvar = 100;
printf("Before fork()\n");
pid_t cpid = vfork();
if (cpid == 0){
gvar++;
lvar++;
printf("I am child and I have incremented my gvar and lvar\n");
printf("Global var= %d, Local var= %d\n",gvar,lvar);
exit(0);
}
else{
printf("\nI am parent now...\n");
printf("Global var= %d, Local var= %d\n",gvar,lvar);
exit(0);
}
}
notice since parent and child are sharing same virutal memory space , printed values are same even though only child process increased the variable's value.
Copy On Write Semantics
after fork both child and parent are pointing the same physical memory. but if one of them try to change or write something on memory. a page fault occurs and the the page is copied and inserted in the page table for that particular process.
Orphan Processes
if a parent has terminated before reaping its children, and the child process is still running, then these children are called orphans.
they can be adopted by init or systemd which do the reaping.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
pid_t cpid = fork();
if (cpid == 0){
printf("Running child, PID=%ld PPID=%ld\n",(long)getpid(), (long)getppid());
while(1);
}
else{
printf("Terminating parent, PID=%ld PPID=%ld\n",(long)getpid(), (long)getppid());
exit(0);
}
return 0;
}
Zombie Processes
processes which have terminated but their parents have not collected their exit status and has not reaped them are called zombies or defunct.
when a process terminates but still is holding system resources like PCB and various tables maintained by OS. it is holding resoruces but never scheduled on the cpu.
can be killed only if parent process get killed.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(){
pid_t cpid = fork();
if (cpid == 0){
printf("Terminating child with PID = %ld\n", (long)getpid());
exit (0);
}
else{
printf("Running parent, PID=%ld\n",(long)getpid());
while(1);
}
return 0;
}
wait system call
the process that calls the wait() system call gets blocked untill any one of its child terminates.
on sucess , the wait system call returns PID of the terminated child and in case of error returns a -1.
Notify parent that a child process finished running, tell the parent how a child process finished.
it is not possible to wait for a particular child , parent can only wait for the first child that terminates
it is not possible to perform a non blocking wait so that if no child has yet terminated , parent get an indication of this fact.
we can use waitpid system call which is better.
all this information is encoded in the status argument of th ewait() system call.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
pid_t cpid = fork();
if (cpid == 0){
printf("Hello I m Child.\n");
sleep(1);
printf("I m Child again, and my PID is %ld\n", getpid());
sleep(1);
printf("I m Child again, and I am terminating...\n");
sleep(1);
exit(7);
}
else{
int status;
pid_t rv = wait (&status);
printf ("Hello I m Parent.\n");
int low_8 = status & 0xff;
int high_8 = status >> 8;
if(low_8 == 0)
printf("Return value of wait is %ld, and status is %d\n",rv, high_8);
exit(54);
}
}
notice since we terminated normally our exit status (7) is at 15~8 bits postion. so we verify with "if low_8 == 0" statement. if it is zero we just print right shifted value which is high_8.
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
void disp_status(int);
int main(){
pid_t cpid = fork();
if (cpid == 0){
printf("I am child process and I am running...\n");
//exit(7);
int j = 0;
int i = (2 / j);
}
else{
int status;
pid_t rv = wait (&status);
printf ("Hello I m Parent.\n");
disp_status(status);
exit(54);
}
}
void disp_status(int status){
//normal termination
int low_7 = status & 0x7f;
int high_8 = status >> 8;
if(low_7 == 0)
printf("My child terminated normally with exit value %d\n", high_8);
//killed by a signal
if(high_8 == 0)
printf("My child was killed by Signal Number = %d\n", low_7);
int bit_7 = status & 0x80;
bit_7 = bit_7 >> 7;
if(bit_7 == 1)
printf("Core Dump file generated.\n");
//stopped by a signal
if(low_7 == 0x7F)
printf("My child was stopped by Signal Number = %d\n", high_8);
//continued by SIGCONT
int low_16 = status & 0xffff;
if(low_16 == 0xffff)
printf("My child continued its execution due to SIGCONT\n");
}
to classify all case we implemented disp_status function.
void disp_status(int status){
//normal termination
if(WIFEXITED(status))
printf("My child terminated normally with exit value %d\n", WEXITSTATUS(status));
//killed by a signal
else if (WIFSIGNALED(status)){
printf("My child was killed by Signal Number = %d\n",WTERMSIG(status));
if(WCOREDUMP(status))
printf("Core Dump file generated.\n");
}
//stopped by a signal
else if (WIFSTOPPED(status))
printf("My child was stopped by Signal Number = %d\n", WSTOPSIG(status));
//continued by SIGCONT
else if (WIFCONTINUED(status))
printf("My child continued its execution due to SIGCONT\n");
}
but instead of bit operators we can use macros to decipher the status argument of wait() system call, defined in /usr/include/x86_84-linux-gnu/bits/waitstatus.h
waitpid system call
it can waits for the child whose PID equals the value of pid (argument of this function)
'Operating System > System Programming(Arif Butt)' 카테고리의 다른 글
Lec20) Design and Code Of Daemon Processes (0) | 2021.07.12 |
---|---|
Lec19) Process Management-III (0) | 2021.07.11 |
Lec17) Process Management-I (0) | 2021.07.09 |
Lec16) Programming Terminal Devices (0) | 2021.07.08 |
Lec15) Design and Code Of UNIX who Utility , Buffering (0) | 2021.07.06 |