C Programming

Execv() Function in C Language

There are several ways and functions to start the processes from a program. Each of them offers different solutions to the programmer depending on the needs of the particular case.

The execXX() family is a set of system functions that are defined in the “unistd.h” header to run a process from within a program. This family of functions allows us to send the input arguments to the executable that calls it which is why it is a very useful resource for interaction between processes.

In this Linux Hint article, you’ll learn all about the execv() function in the C language. We will look at its syntax, the theoretical description of how it works, the input and output arguments, and the type of data that each of them processes. You’ll also learn how to create and use the arrays of strings and pointers that are part of the input arguments of this family of functions and are passed to the calling process.

Then, we apply what we learned in a practical example that shows the correct implementation and calling of the execv() function.

Syntax of the Execv() Function in C Language

 

int execv( const char *path, char *const argv[]);

 

Description of the Execv() Function in C Language

The execv() function executes a process from another process or program. This function executes the file or executable which is specified in the *path argument. This entry should contain the absolute or relative path of the executable file in string format.

The *argv[] argument is an array of pointers to strings where each string is an input argument that is passed to the process to be executed. The first pointer of the array should always point to a string that contains the name of the executable file and the last pointer should always be NULL. When execv() is called, the process from which it was called is terminated, rewritten, and replaced by the new process in the allocated portion of memory and with the same ID.

If the function is performed successfully, it does not return. If it returns, it is because an error occurs. The errors that this function can generate are varied, ranging from the non-existing executable file path to denied permissions.

The error can be identified by retrieving its value from the errno global variable. On the later part, we will see a special section which explains the most common errors of this function and their identification.

The family of execXX() functions is defined in the “unistd.h” header. To use them, we must include them in our “.c” file as follows:

#include  <unistd.h>

 

How to Execute a Process from a Program Using the Execv() Function in C Language

In this example, we will explain how to use the execv() function to execute a process and pass the input arguments from one program to another.

To do this, we create two very simple codes. One is the parent process which calls the execv() function to execute the child process. When the execv() function starts the child process, it passes it with three input arguments in the form of a string that the child process retrieves and displays on the shell.

Child Process

The child process is a simple piece of code that prints the “I am the child process” message, retrieves the input arguments that are sent by the parent process, and displays them on the shell. Here is the code for the child process:

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

int main(int argc, char *argv[])
{
 printf ("I am the child process");

 printf ("Argument 1: %s\n", argv[1]);
 printf ("Argument 2: %s\n", argv[2]);
 printf ("Argument 3: %s\n", argv[3]);

}

 
We compile this code and save its production in “Documents” under the “child” name with the “.bin” extension as shown in the following:

~$ gcc Documents/child.c -o Documents/child.bin

 
In this way, we save the child executable file in “Documents”. The path of this executable is the input argument, path, when calling execv() in the parent process.


Parent Process

The parent process is the one from which we call the execv() function to execute the child process. In this code, we define an array of pointers to the strings that represent the input arguments to the process that the execv() function opens.

You can see how to correctly create an array of pointers to strings in the following illustration. In this case, it consists of 5 pointers and is called arg_Ptr[].

char *arg_Ptr[5];

 
Once the array of pointers is defined, each pointer must be assigned a string which contains the input argument that we send to the child process.

You can see how to assign each pointer with its corresponding argument in string format in the following illustration:

arg_Ptr[0] = "child.c";
arg_Ptr[1] = "\nHello from ";
arg_Ptr[2] = " process 2 ";
arg_Ptr[3] = NULL;

 
Another way to assign the strings to the pointer array is to enclose the strings in curly braces and separate them with commas:

arg_Ptr[] = {"child.c, "\nHello from ", " process 2 ", NULL};

 
After defining the array of pointers to each argument, the next step is to call the execv() function, passing the string which contains the absolute or relative path of the executable file as the first argument and the array of strings arg_Ptr[]as the second argument.

You can see the complete “main” of the parent process in the following illustration:

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

int main (){
printf ("\n\nI am the parent process\n");
char *arg_Ptr[5];
arg_Ptr[0] = " child.c";
arg_Ptr[1] = " \nHello from ";
arg_Ptr[2] = " process 2 ";
arg_Ptr[3] = NULL;

execv("/home/linuxhint/child.bin", arg_Ptr);
}

 
We compile this code which specifies the path of the “.c” file and the name of the out.

~$ gcc Documents/parent.c -o pattern

 
Then, we run the output.

~$ ./ pattern

 
The parent process displays the “I am the parent process” message, creates the string array by assigning a string for each input argument which is passed to the next process, and calls the execv() function. If the execv() function executes successfully, the child.bin executable replaces the parent process and takes over its ID and allocated memory, so this action cannot be undone.

The child process displays the “I am the child process” message and retrieves each of the input arguments which are passed by the parent process to display on the command console.

How to Recognize Possible Errors When Using the Execv() Function

The execv() function does not return if it is executed successfully. If it returns to the code that called it, an error has occurred. The errors that can be generated by this function are manifold since the operation depends on two different processes, file paths, access permissions, and so on.

The way to identify the error is through the errno global variable. This variable is an integer and is defined in the “errno.h” header. Each time an error occurs, a numeric value that represent a particular error is stored in it.

Next, we look at the definitions and representative value of the possible errors that can occur when using this function:


We generate an error in the patern.c code, indicating a non-existent file path to the execv() function. Then, use the printf function to display the error code which is obtained from the errno variable in the console:

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

int main (){
printf ("\n\nI am the parent process\n");
char *arg_Ptr[5];
arg_Ptr[0] = " child.c";
arg_Ptr[1] = " \nHello from ";
arg_Ptr[2] = " process 2 ";
arg_Ptr[3] = NULL;

execv("/home/linuxhint/non existent.bin", arg_Ptr);
printf ( "Error:  %i\n", errno);
}

 
As we can see in the following figure, the execv() function could not find the file with the specified path and therefore returns to the parent process with the value 2 in the errno variable which corresponds to the “No such file or directory” error.

Conclusion

In this Linux Hint article, we explained how to use the execv() function in the C language to start a process from another process. We explained the theoretical operation of execv() and showed how to declare the input arguments.

We then implemented what we learned in an example, showing you how to create the parent program and the child process by passing the arguments from one to the other. Also, we saw a special section where we show the most common errors of this function and how to identify them using the errno variable.

We hope that this article is useful for you. For more articles about the C language and Linux tips, use the search engine on our website.

About the author

Julio Cesar

Julio Cesar is a 42 years old programmer with 8 years of experience in embedded systems development, 6 years developing firmware for user interfaces in C and C++. Additionally he has 2 years of experience developing scripts for network devices and 3 years as developer of high frequency PCB (Printed Circuit Board).