Article directory
Introduction to exec
View help via command:man 3 exec
The function of the exec function family is to find the executable file based on the specified file name and use it to replace the content of the calling process. In other words, it is to execute an executable file inside the calling process .
Functions in the exec function family will not return after successful execution, because the entities of the calling process, including code segments, data segments, and stacks, have been replaced by new content, leaving only some superficial information such as process IDs. Only if the call fails, they will return -1 and continue execution from the calling point of the original program.
Picture reference from: [Linux] Understanding and using process control (exec function family)
Process program replacement does not create a new process, it only loads the program's code and data to replace the original process.
exec family
int execl(const char *path, const char *arg, .../* (char *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
int execle(const char *path, const char *arg, .../*, (char *) NULL, 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[]);
int execve(const char *filename, char *const argv[], char *const envp[]);
return value
- Functions in the exec function family will not return after successful execution.
- The call failed and -1 was returned.
Followed by different parameters, representing different meanings
-
l(list): parameter address list, terminated by a null pointer
-
v(vector): The address of the pointer array that stores the address of each parameter
-
p(path): Search for executable files in the directory specified by the PATH environment variable. You can use env to view existing environment variables.
-
e (environment): The address of the pointer array that stores the string address of the environment variable
The first two are used more often
execl function
-
int execl(const char *path, const char arg, …/ (char *) NULL */);
-
path: the path or name of the file to be executed that needs to be specified
-
arg: is the list of parameters required to execute the executable file. The first parameter generally has no effect. For convenience, it usually writes the name of the program to be executed. Starting from the second parameter, it is the list of parameters required for program execution. The parameters need to end with NULL (Sentinel)
-
Note: There are 2 files in the initial folder hello.c
, the content of which is to output a random statement.hello
program
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
int main() {
// 创建一个子进程,在子进程中执行exec函数族中的函数
pid_t pid = fork();
if(pid > 0) {
// 父进程
printf("i am parent process, pid : %d\n",getpid());
sleep(1);
}else if(pid == 0) {
execl("hello","hello",NULL);
perror("execl");
printf("i am child process, pid : %d\n", getpid());
}
for(int i = 0; i < 3; i++) {
printf("i = %d, pid = %d\n", i, getpid());
}
return 0;
}
operation result
(base) user@ubuntu:~/Desktop/OS/NiuKe$ gcc -o test test.c -std=c99
(base) user@ubuntu:~/Desktop/OS/NiuKe$ ./test
i am parent process, pid : 4426
Hello world
i = 0, pid = 4426
i = 1, pid = 4426
i = 2, pid = 4426
As you can see, the content of the child process (user area) is replaced, and the content in the hello executable file is printed.
execlp function
-
int execlp(const char *file, const char arg, … / (char *) NULL */);
-
It will search for the specified executable file in the environment variable. If it is found, it will be executed. If it is not found, the execution will not be successful.
-
file: only the name needs to be provided (the path does not need to be provided)
-
program
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main() {
// 创建一个子进程,在子进程中执行exec函数族中的函数
pid_t pid = fork();
if(pid > 0) {
// 父进程
printf("i am parent process, pid : %d\n",getpid());
sleep(1);
}else if(pid == 0) {
// 子进程
execlp("ps", "ps", "aux", NULL);
printf("i am child process, pid : %d\n", getpid());
}
for(int i = 0; i < 3; i++) {
printf("i = %d, pid = %d\n", i, getpid());
}
return 0;
}
Output results
(base) user@ubuntu:~/Desktop/OS/NiuKe$ gcc -o test test.c -std=c99
(base) user@ubuntu:~/Desktop/OS/NiuKe$ ./test
i am parent process, pid : 4437
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.2 160048 9248 ? Ss Jan15 0:03 /sbin/init auto noprompt
root 2 0.0 0.0 0 0 ? S Jan15 0:00 [kthreadd]
root 3 0.0 0.0 0 0 ? I< Jan15 0:00 [rcu_gp]
root 4 0.0 0.0 0 0 ? I< Jan15 0:00 [rcu_par_gp]
root 6 0.0 0.0 0 0 ? I< Jan15 0:00 [kworker/0:0H-kb]
...
user 4438 0.0 0.0 41424 3568 pts/3 R+ 00:51 0:00 ps aux
i = 0, pid = 4437
i = 1, pid = 4437
i = 2, pid = 4437
execv function
-
int execv(const char *path, char *const argv[]);
- argv: Write all running parameters in the array
program
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
int main() {
// 创建一个子进程,在子进程中执行exec函数族中的函数
pid_t pid = fork();
if(pid > 0) {
// 父进程
printf("i am parent process, pid : %d\n",getpid());
sleep(1);
}else if(pid == 0) {
// 子进程
char* argv[] = {
"hello", NULL};
execv("hello", argv);
perror("execv");
printf("i am child process, pid : %d\n", getpid());
}
for(int i = 0; i < 3; i++) {
printf("i = %d, pid = %d\n", i, getpid());
}
return 0;
}
Output results
(base) user@ubuntu:~/Desktop/OS/NiuKe$ gcc -o test test.c -std=c99
(base) user@ubuntu:~/Desktop/OS/NiuKe$ ./test
i am parent process, pid : 4453
Hello world
i = 0, pid = 4453
i = 1, pid = 4453
i = 2, pid = 4453
The remaining functions are similar in usage and will not be shown~