在当前进程中载入并运行程序,让特定的程序进入特定的进程运行

覆盖当前进程的代码、数据、栈(只继承了躯体是吧 hhh)

程序在加载以及运行的过程中,除了需要使用 Fork 函数之外,还需要函数 Execve
但是 execve 不会返回,调用 execve 需要传入三个参数

#include<unistd.h>
int execve(const char *filename, const char *argv[], const char *envp[]);

argv[] 是指针数组,以 null 结尾
envp[] 是指针数组,以 null 结尾, 环境变量包括当前的工作目录、PWD、用户名等信息。

函数 execve 的作用就是调用加载器,在执行可执行程序 main 函数之前,启动代码需要设置用户栈,并将控制传递给新程序的主函数。

main 函数开始执行时,用户栈的结构

什么样的执行流程

就是我们父进程在这运行的时候,如果它要加载一个文件,那我们就调用这个函数,这个文件可能是我们生成的这个可执行目标文件,filename 是可执行目标文件的名字,然后我们会把这个可执行目标文件的 data 区,就是数据区和代码区给加载到当前我们执行的这个父进程里,它的虚拟地址空间里面的 data 和数据区给它覆盖掉,就把这两号给覆盖掉,覆盖掉,然后这前面就是栈了,这上面就是栈,那栈的时候会给它加载一些新的东西,栈加载就是这两块一个参数列表,一个环境变量,然后加载完之后我们就会跳到那个 main 函数主程序里面去执行

使用细则

exec 用被执行的程序完全替换调用它的程序的影像。fork 创建一个新的进程就产生了一个新的 PID,
exec启动一个新程序,替换原有的进程,因此这个新的被exec执行的进程的PID不会改变,
和调用exec函数的进程一样。

int execl(char *pathname, char *arg0, char *arg1, ..., char *argn, NULL)
int execle(char *pathname, char *arg0, char *arg1, ..., char *argn, NULL, char *envp[])
int execlp(char *pathname, char *arg0, char *arg1, ..., NULL)
int execlpe(char *pathname, char *arg0, char *arg1, ..., NULL, char *envp[])
int execv(char *pathname, char *argv[])
int execve(char *pathname, char *argv[], char *envp[])
int execvp(char *pathname, char *argv[])
int execvpe(char *pathname, char *argv[], char *envp[])

exec函数族装入并运行程序pathname,并将参数arg0(arg1,arg2,argv[],envp[])传递给子程序,出错返回-1

在exec函数族中,后缀l、v、p、e添加到exec后,所指定的函数将具有某种操作能力

  • p:函数可以利用DOS的PATH变量查找子程序文件。

  • l:希望接收以逗号分隔的参数列表,列表以NULL指针作为结束标志

     

execl(“/bin/cat”, “/etc/passwd”, “/etc/group”, NULL);

 
*   v:希望接收到一个以NULL结尾的字符串数组的指针
 
    ```c
char* argv[] = {"/bin/cat", "/etc/passwd", "/etc/group", NULL};
execv("/bin/cat", argv);
  • e:函数传递指定参数envp,允许改变子进程的环境,无后缀e时,子进程使用当前程序的环境。

envp也是一个以NULL结尾的字符串数组指针