Overlaying Process Image



Assume that we are running a program and we want to run another program from the current program. Is this possible? Why not, if we implement the concept of overlaying the process image. That’s fine but what about the current running program, can that be run too. How is it possible, since we overlaid the current program with the new program. What to do, if I want to run the two programs without losing the current running program, is it possible? Yes, it is possible.

Create a child process, so that we have a parent process and a newly created child process. Already we are running the current program in the parent process, so run the newly created process in the child. In this way, we can run another program from the current program. Not only a single program but we can run any number of programs from the current program by creating that many number of child processes.

Let us consider the following program as an example.

/* File Name: helloworld.c */

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

/* File Name: execl_test.c */

#include<stdio.h>
#include<unistd.h>

void main() {
   execl("./helloworld", "./helloworld", (char *)0);
   printf("This wouldn't print\n");
   return;
}

The above program would overlay the process image of execl_test with helloworld. That is the reason, the process image code of execl_test (printf()) is not executed.

Compilation and Execution Steps

Hello World

Now, we will run the following two programs from one program, i.e., execl_run_two_prgms.c.

  • Hello World program (helloworld.c)

  • While loop program to print from 1 to 10 (while_loop.c)

/* File Name: while_loop.c */

/* Prints numbers from 1 to 10 using while loop */
#include<stdio.h>

void main() {
   int value = 1;
   while (value <= 10) {
      printf("%d\t", value);
      value++;
   }
   printf("\n");
   return;
}

Following is the program to run two programs (one program from child and another program from parent).

/* Filename: execl_run_two_prgms.c */

#include<stdio.h>
#include<unistd.h>

void main() {
   int pid;
   pid = fork();
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      execl("./helloworld", "./helloworld", (char *)0);
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

Note − Place sleep() call to make sure the child and parent processes run sequentially (do not overlap the result).

Compilation and Execution Steps

Child process: Running Hello World Program
This wouldn't print
Parent process: Running While loop Program
Won't reach here

Now we would run two programs from one program i.e., execl_run_two_prgms.c, same program as above but with command line arguments. So, we are running two programs namely, helloworld.c in the child process, and the program while_loop.c in the parent process. This is as follows −

  • Hello World program (helloworld.c)

  • While loop program to print from 1 to num_times_str as per command line arguments (while_loop.c)

This program broadly performs the following actions −

  • Creates a child process

  • Child process executes helloworld.c program

  • Parent process executes while_loop.c program passing the command line argument value as an argument to the program. If the command line arguments are not passed, then the default is taken as 10. Otherwise, it takes the given argument value. The argument value should be numeric; code would not validate if given in alphabets.

/* Filename: execl_run_two_prgms.c */

#include<stdio.h>
#include<string.h>
#include<unistd.h>

void main(int argc, char *argv[0]) {
   int pid;
   int err;
   int num_times;
   char num_times_str[5];
   
   /* In no command line arguments are passed, then loop maximum count taken as 10 */
   if (argc == 1) {
      printf("Taken loop maximum as 10\n");
      num_times = 10;
      sprintf(num_times_str, "%d", num_times);
   } else {
      strcpy(num_times_str, argv[1]);
      printf("num_times_str is %s\n", num_times_str);
      pid = fork();
   }
   
   /* Child process */
   if (pid == 0) {
      printf("Child process: Running Hello World Program\n");
      err = execl("./helloworld", "./helloworld", (char *)0);
      printf("Error %d\n", err);
      perror("Execl error: ");
      printf("This wouldn't print\n");
   } else { /* Parent process */
      sleep(3);
      printf("Parent process: Running While loop Program\n");
      execl("./while_loop", "./while_loop", (char *)num_times_str, (char *)0);
      printf("Won't reach here\n");
   }
   return;
}

Following is the helloworld.c program called from the child process of the program, execl_run_two_prgms.c.

/* File Name: helloworld.c */

#include<stdio.h>

void main() {
   printf("Hello World\n");
   return;
}

Following is the while_loop.c program called from the parent process of the program, execl_run_two_prgms.c. The argument to this program is passed from the program which runs this i.e., execl_run_two_prgms.c.

/* Filename: while_loop.c */

#include<stdio.h>

void main(int argc, char *argv[]) {
   int start_value = 1;
   int end_value;
   if (argc == 1)
   end_value = 10;
   else
   end_value = atoi(argv[1]);
   printf("Argv[1] is %s\n", argv[1]);
   while (start_value <= end_value) {
      printf("%d\t", start_value);
      start_value++;
   }
   printf("\n");
   return;
}

Compilation and Execution Steps

Taken loop maximum as 10
num_times_str is 10
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 10
1 2 3 4 5 6 7 8 9 10
Taken loop maximum as 15
num_times_str is 15
Child process: Running Hello World Program
Hello World
Parent process: Running While loop Program
Argv[1] is 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Let us now see the overlaying image related library functions.

#include<unistd.h>

int execl(const char *path, const char *arg, ...);

This function would overlay the current running process image with the new process as mentioned in the arguments, path and arg. If any argument needs to passed to a new process image, that would be send through “arg” arguments and the last argument should be NULL.

This function would return a value only in case of an error. The process overlaying image related calls are as mentioned below −

int execl(const char *path, const char *arg, ...);
int execlp(const char *file, const char *arg, ...);
int execle(const char *path, const char *arg, ..., char * const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execvpe(const char *file, char *const argv[], char *const envp[]);

These calls would address passing command line arguments (argv[]), environment variables (envp[]) and other parameters.

Advertisements