Tut 5
Tut 5
Yemineni Ashok
BITS Pilani Computer Science and Information Systems Department
BITS, Pilani
Pilani Campus
3
BITS Pilani, Pilani Campus
Process
4
BITS Pilani, Pilani Campus
Process
• Includes
– The program code, also called text section
– Current activity including value of program
counter and processor registers
– Stack containing temporary data
• Function parameters, return addresses, local variables
– Data section containing global variables
– Heap containing memory dynamically allocated
during run time
Temporary data,
Local variables
Local variables
(inside function)
vs
Global variable Dynamic memory
(outside function)
Global variables
program code
• Address space
– Child process is duplicate of parent process
– Child process has a program loaded into it
• UNIX examples
– fork system call creates new process
– exec system call used after a fork to replace the
process’ memory space with a new program
#include <sys/types.h>
#include <studio.h>
#include <unistd.h>
int main()
{
pid_t pid;
/* fork another process */
pid = fork();
if (pid < 0) { /* error occurred */
fprintf(stderr, "Fork Failed");
return 1;
}
else if (pid == 0) { /* child process */
execlp("/bin/ls", "ls", NULL);
}
else { /* parent process */
/* parent will wait for the child */
wait (NULL);
printf ("Child Complete");
}
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include<sys/types.h>
int main() {
printf("I am process %ld\n",(long)getpid());
printf("My Parent is %ld\n",(long)getppid());
}
output
Ashok@Ashok-Latitude-E5450:~$ ./a.out
I am process 3193
My Parent is 2981
12
BITS Pilani, Pilani Campus
fork() and exec() system calls
fork()
It creates a new process which is an identical copy of an existing process.
The newly created process will contain all the instructions and data of its
parent process.
Hence it executes the same parent process.
fork() is the only way to create new processes in UNIX
exec()
This on the other hand re-initializes the existing process with some other
designated program.
It does not create a new process.
It merely flushes the current context of a program and loads a new context
(new program).
exec() call is the only way to execute programs in UNIX. In fact, the kernel
boots itself using the exec() call.
BITS Pilani, Pilani Campus
fork() system call
fork() call creates a “new” process.
The child process’ context will be the same as the parent
process.
After a fork() call, two copies of the same context exist, one
belonging to the child and another to the parent.
Contrast this to exec(), where a single context will exist
because of child context over-writing the parent.
# include<unistd.h>
int fork(void);
/*Returns child process-ID and 0 on success and -1 on
error */
1# include<stdio.h>
2 int main(void){
3 printf(“************ Before Fork************\n”);
4 system(“ps”);
5
6 fork();
7
8 printf(“************ After Fork *************\n”;
9 system(“ps”);
10 return 0;
11}
int main(void) {
pid_t pid;
printf("************ Before Fork************\n");
system("ls -l");
pid = fork();
if(pid == 0){
printf("************ After Fork *************\n");
system("ps");
}
else if (pid > 0)
wait();
return 0; }
BITS Pilani, Pilani Campus
[user@localhost processes]$ ./a.out
************ Before Fork************
total 60
-rwxrwxr-x. 1 user user 6937 Sep 13 16:30 a.out
-rw-rw-r--. 1 user user 310 Sep 6 16:48 env.c
-rw-rw-r--. 1 user user 145 Sep 6 17:06 execL.c
-rw-rw-r--. 1 user user 219 Sep 13 15:50 execlp.c
-rw-rw-r--. 1 user user 219 Sep 5 15:41 pid_ppid.c
-rwxrwxr-x. 1 user user 6919 Sep 13 13:16 sum
-rw-rw-r--. 1 user user 280 Sep 13 13:16 sum.c
-rw-rw-r--. 1 user user 326 Sep 2 13:03 system1.c
************ After Fork *************
PID TTY TIME CMD
2806 pts/0 00:00:00 bash
3565 pts/0 00:00:00 a.out
3567 pts/0 00:00:00 a.out
3568 pts/0 00:00:00 ps
BITS Pilani, Pilani Campus
int main(int argc, char *argv[]){
int pid;
printf("*****before fork****\n ");
system("ps");
pid = fork();
if(pid == 0)
{
printf("*****after fork****\n ");
printf("child pid = %d\n",pid);
//execl("/bin/echo","echo","hello","world",(char *)NULL);
execlp("echo","echo","hello","world",(char *)NULL);
}
else {
printf("parent pid = %d\n",pid);
wait();
}
return 0; }
BITS Pilani, Pilani Campus
output
#include <stdio.h>
#include <sys/types.h>
int main()
{
fork();
fork();
fork();
printf("hello\n");
return 0;
}
24
BITS Pilani, Pilani Campus
output
25
BITS Pilani, Pilani Campus
Forking Cost
• fork() calls are enormously costly in terms of computing resources.
• A clone of the parent’s context is made which involves copying of the data
segment.
• Copy of instruction segment (code) is not made because the segment is read-
only and hence is shared between parent and child.
• The data segment can be very huge. if fork() is immediately followed by
exec() then it overwrites the existing data and code segments. Hence copying
data segment is wasted.
• A scheme that overcomes this handicap is called the “copy-on-write” scheme.
• In this scheme, after fork() the parent and the child share the same data
segment as long as the data segment is unmodified. When the parent or child
modifies a particular page, a copy of only that page is made. So, there would
be two copies of modified pages while the unmodified pages would be
shared.
• Repeated fork() calls (also known as fork bombs) can eventually lead to resource
exhaustion and may collapse the system.
int main(void){
int cnt=0; int pid;
for(cnt=0;cnt<3;cnt++){
pid=fork();
if(pid==0)
continue;
else
break;
}
printf("Process %d\n",getpid());
return 0;
}
Exec()
This on the other hand re-initializes the existing process with some
other designated program.
It does not create a new process.
It merely flushes the current context of a program and loads a new
context (new program).
exec() call is the only way to execute programs in UNIX. In fact, the
kernel boots itself using the exec() call.
fork() is the only way to create new processes in UNIX
3 l p execlp Execute file with arguments explicitly in call and PATH search
5 l e execle Execute file with argument list and manually passed environment
pointer
6 v e execve Execute file with argument vector and manually passed
environment pointer
int execvp (
const char *file, /* Program filename */
char* const argv[] /* Argument vector */
);
int execve (
const char *path, /* Program pathname */
char *const argv[], /* Argument vector */
char *const envv[] /* Environment vector */
);
BITS Pilani, Pilani Campus
int execlp (
const char *file, /* Program filename */
const char *arg0, /*First Argument(filename) */
const char *arg1,
…
(char *) NULL /* Arg list terminator */
);
int execle (
const char *path, /* Program pathname */
const char *arg0, /*First Argument(filename) */
const char *arg1,
…
(char *) NULL, /* Arg list terminator */
char *const envv[] /* Environment vector */
);
BITS Pilani, Pilani Campus
execl() system Call
It execute file with arguments explicitly in call.
Syntax
int execl (
const char *path, /* Complete Program pathname */
const char *arg0, /* First Argument(filename) */
const char *arg1, /* Second Argument(optional) */
… /* Remaining Arguments (if any) */
(char *) NULL /* Arg list terminator */
);
/* Returns -1 on error (sets errno) */
#include<stdio.h>
#include<unistd.h>
#include<errno.h>
#include <unistd.h>
int main(void) {
char *binaryPath = "/bin/bash";
char *const args[] = {binaryPath, "-c", "echo YOU ARE THE PART OF $A $B ", NULL};
char *const env[] = {“A=BITS“,”B=PILANI”, NULL};
Just like execle() you can provide your own environment variables
along with execve(). You can also pass arguments as arrays as you
did in execv().
44
BITS Pilani, Pilani Campus
Any Queries?