OS-LAB#5 Processes in C
OS-LAB#5 Processes in C
Lab # 05:
Processes in Linux/Unix
Instructor: Dr Mumtaz Ali Kaloi
Submission Profile
Comments: ______________________________________________________________________
Objectives:
Introduction:
Variable Length Argument in C:
Variable length argument is a feature that allows a function to receive any number of arguments. There
are situations where we want a function to handle variable number of arguments according to
requirement. 1) Sum of given numbers. 2) Minimum of given numbers. and many more. Variable number
of arguments are represented by three dotes (…) Below is an example, to find minimum of given set of
integers.
// number of arguments.
#include <stdarg.h>
#include <stdio.h>
// of numbers.
int i;
int min, a;
// variable arguments
va_list ap;
// va_start must be called before accessing
va_start(ap, arg_count);
// argument in list
min = a;
va_end(ap);
return min;
// Driver code
int main()
int count = 5;
return 0;
Examle2
// of multiple numbers.
#include <stdarg.h>
#include <stdio.h>
va_list valist;
int sum = 0, i;
va_start(valist, num);
// Driver code
int main()
return 0;
There is a whole family of related functions grouped under the exec heading. They differ in the way that
they start processes and present program arguments. An exec function replaces the current process with a
new process specified by the path or file argument. You can use exec functions to “hand off” execution
of your program to another. For example, you could check the user’s credentials before starting another
application that has a restricted usage policy. The exec functions are more efficient than system because
the original program will no longer be running after the new one is stated.
#include <unistd.h>
char **environ;
int execl(const char *path, const char *arg0, ..., (char *)0);
int execlp(const char *file, const char *arg0, ..., (char *)0);
int execle(const char *path, const char *arg0, ..., (char *)0, char *const
envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
These functions belong to two types. execl, execlp, and execle take a variable number of arguments
ending with a null pointer. execv and execvp have as their second argument an array of strings. In both
cases, the new program starts with the given arguments appearing in the argv array passed to main. These
functions are usually implemented using execve, though there is no requirement for it to be done this way.
The functions with names suffixed with a p differ in that they will search the PATH environment variable
to find the new program executable file. If the executable isn’t on the path, an absolute filename,
including directories, will need to be passed to the function as a parameter. The global variable environ is
available to pass a value for the new program environment. Alternatively, an additional argument to the
functions execle and execve is available for passing an array of strings to be used as the new program
environment. If you want to use an exec function to start the ps program, you can choose from among the
six exec family functions, as shown in the calls in the code fragment that follows:
#include <unistd.h>
/* Example of an argument list */
/* Note that we need a program name for argv[0] */
char *const ps_argv[] =
{“ps”, “ax”, 0};
/* Example environment, not terribly useful */
char *const ps_envp[] =
{“PATH=/bin:/usr/bin”, “TERM=console”, 0};
/* Possible calls to exec functions */
execl(“/bin/ps”, “ps”, “ax”, 0); /* assumes ps is in /bin */
execlp(“ps”, “ps”, “ax”, 0); /* assumes /bin is in PATH */
execle(“/bin/ps”, “ps”, “ax”, 0, ps_envp); /* passes own environment */
execv(“/bin/ps”, ps_argv);
execvp(“ps”, ps_argv);
execve(“/bin/ps”, ps_argv, ps_envp);
execlp call:
Example# 1
To use processes to perform more than one function at a time, you can either use threads, or create an
entirely separate process from within a program, as init does, rather than replace the current thread of
execution, as in the exec case. You can create a new process by calling fork. This system call duplicates
the current process, creating a new entry in the process table with many of the same attributes as the
current process. The new process is almost identical to the original, executing the same code but with its
own data space, environment, and file descriptors. Combined with the exec functions, fork is all you need
to create new processes.
#include <sys/types.h>
#include <unistd.h>
pid_t fork(void);
As you can see in Figure 1-1, the call to fork in the parent returns the PID of the new child process. The
new process continues to execute just like the original, with the exception that in the child process the call
to fork returns 0. This allows both the parent and child to determine which is which. If fork fails, it returns
-1. This is commonly due to a limit on the number of child processes that a parent may have
(CHILD_MAX), in which case errno will be set to EAGAIN. If there is not enough space for an entry in
the process table, or not enough virtual memory, the errno variable will be set to ENOMEM.
Figure 1-1
Example# 2
Fork
When you start a child process with fork, it takes on a life of its own and runs independently. Sometimes,
you would like to find out when a child process has finished. For example, in the previous program, the
parent finishes ahead of the child and you get some messy output as the child continues to run. You can
arrange for the parent process to wait until the child finishes before continuing by calling wait.
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *stat_loc);
The wait system call causes a parent process to pause until one of its child processes is stopped. The call
returns the PID of the child process. This will normally be a child process that has terminated. The status
information allows the parent process to determine the exit status of the child process, that is, the value
returned from main or passed to exit. If stat_loc is not a null pointer, the status information will be written
to the location to which it points.
Wait:
You modify the program slightly so you can wait for and examine the child process exit status. Call the
new program wait.c.
Example# 3
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main() {
pid_t pid;
char *message;
int n;
int exit_code;
printf(“fork program starting\n”);
pid = fork();
switch(pid){
case -1:
perror(“fork failed”);
exit(1);
case 0:
message = “This is the child”;
n = 5;
exit_code = 37;
break;
default:
message = “This is the parent”;
n = 3;
exit_code = 0;
break;
}
for(; n > 0; n--) {
puts(message);
sleep(1);
}
This section of the program waits for the child process to finish.
if (pid != 0) {
int stat_val;
pid_t child_pid;
child_pid = wait(&stat_val);
printf(“Child has finished: PID = %d\n”, child_pid);
if(WIFEXITED(stat_val))
printf(“Child exited with code %d\n”, WEXITSTATUS(stat_val));
else
printf(“Child terminated abnormally\n”);
}
exit(exit_code);
}
When you run this program, you see the parent wait for the child.
$ ./wait
fork program starting
This is the child
This is the parent
This is the paren
tThis is the child
This is the parent
This is the child
This is the child
This is the child
Child has finished: PID = 1582
Child exited with code 37
$
How it works:
The parent process, which got a nonzero return from the fork call, uses the wait system call to suspend its
own execution until status information becomes available for a child process. This happens when the
child calls exit; we gave it an exit code of 37. The parent then continues, determines that the child
terminated normally by testing the return value of the wait call, and extracts the exit code from the status
information.
Lab Exercise:
Q1. What is role of functions execl(), execle(), execv(), execvp(), and execve()
Q2. Why we use fork() function