前言
🎬 个人主页:@ChenPi
🐻推荐专栏1: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨
🔥 推荐专栏2: 《C++_@ChenPi的博客-CSDN博客》✨✨✨
🛸推荐专栏3: 《链表_@ChenPi的博客-CSDN博客 》 ✨✨✨
🌺本篇简介 : Linux进程在运行中我们如何进入到另一个进程呢?我们可以使用exec系统调用
Linux 是一个多用户多任务的操作系统,每个用户可以同时运行多个程序
进程是程序运行的主体,包括进程的创建,调度和消亡的整个过程
当用户执行一个指令或者启动一个程序时,就创建了一个进程
一个运行的程序也可能有多个进程。
每个进程将被分配各种资源
一 exec族函数
1.1 exec族函数函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。
1.2 exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe
函数原型:
#include <unistd.h>
extern char **environ;
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[]);
- 返回值:
- exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
- 参数说明:
- path:可执行文件的路径名字
- arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
- file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。
1.3 exec族函数的区别
1.3.1 execl()和 execv()的区别
execl()和 execv()都是基本的 exec 函数,都可用于执行一个新程序,它们之间的区别在于:
参数格式不同,参数 path 意义和格式都相同,指向新程序的路径名,既可以是绝对路径、也可以是相对路径。execl()和 execv()不同的在于第二个参数,execv()的argv 参数与 execve()的 argv 参数相同,也是字符串指针数组;而 execl()把参数列表依次排列,使 用可变参数形式传递,本质上也是多个字符串,以 NULL 结尾,如下所示:
// execv 传参
char *arg_arr[5];
/*参数 argv 则指定了传递给新程序的命令行参数。是一个字符串数组,
该数组对应于 main(int argc, char *argv[])函数的第二个参数 argv,
且格式也与之相同,是由字符串指针所组成的数组,以 NULL 结束。*/
argv[0]对应的便是新程序自身路径名。
arg_arr[0] = "./newApp";
arg_arr[1] = "Hello";
arg_arr[2] = "World";
arg_arr[3] = NULL;
execv("./newApp", arg_arr);
// execl 传参
execl("./newApp", "./newApp", "Hello", "World", NULL);
1.3.2 execlp()和 execvp()的区别
execlp()和 execvp()在 execl()和 execv()基础上加了一个 p,这个 p 其实表示的是 PATH;execl()和execv()要求提供新程序的路径名,而 execlp()和 execvp()则允许只提供新程序文件名,系统会在由 环境变量 PATH 所指定的目录列表中寻找相应的可执行文件,如果执行的新程序是一个 Linux 命 令,这将很有用;当然,execlp()和 execvp()函数也兼容相对路径和绝对路径的方式。
1.3.1 execle()和 execve()的区别
execle()和 execvpe()这两个函数在命名上加了一个 e,这个 e 其实表示的是 environment 环境变量, 意味着这两个函数可以指定自定义的环境变量列表给新程序,参数envp与系统调用execve()的envp参数相同,也是字符串指针数组,使用方式如下所示:
// execvpe 传参
char *env_arr[5] = {"NAME=app", "AGE=25",
"SEX=man", NULL};
char *arg_arr[5];
arg_arr[0] = "./newApp";
arg_arr[1] = "Hello";
arg_arr[2] = "World";
arg_arr[3] = NULL;
execvpe("./newApp", arg_arr, env_arr);
// execle 传参
execle("./newApp", "./newApp", "Hello", "World", NULL, env_arr);
二 exec族函数使用示例
6 个 exec 库函数运行 ls 命令,并加入参数-li。
2.1 execl
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
char ret = execl("/bin/ls","ls","-li",NULL);
if(-1 == ret) //调用失败返回-1
perror("");
}
2.2 execv
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *canshu[] = {"ls","-li",NULL};
execv("/bin/ls",canshu);
}
2.3 execlp
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
execlp("ls","ls","-li",NULL);
}
2.4 execvp
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *canshu[] = {"ls","-li",NULL};
execvp("ls",canshu);
}
2.5 execle
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
char *env_init[] = {"AA=aa","BB=bb",NULL}; //作为参数传到下个执行文件
void main()
{
execle("./test","test",NULL,env_init);
}
2.6 execve
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
void main()
{
char *env_init[] = {"AA=aa","BB=bb",NULL}; //作为参数传到下个执行文件
char *canshu[] = {"test","-li",NULL};
execve("./test",canshu,env_init);
}
2.7 总结:
- l : 使用参数列表
- p:使用文件名,并从PATH环境进行寻找可执行文件
- v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
- e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量