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.
#include<stdio.h> void main() { printf("Hello World\n"); return; }
#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.
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)
/* 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).
#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).
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.
#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.
#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.
#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; }
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.