Linux系统下exec函数族简单介绍

发布时间 2023-03-30 13:44:28作者: nakejimamiyuki

exec()函数的简单介绍

exec函数族的作用是根据指定的文件名找到可执行的文件,并用它来取代调用进程的内容,话句话说,就是在调用进程内部执行一个可执行文件。
exec函数族的函数执行成功后不会返回,因为调用进程的实体。包括代码段,数据段和堆栈等都已被新的内用取代,只留下进程ID等一些表面上的信息让保持原样。看上去是旧的躯壳,却以注入新的灵魂。只有调用失败了,函数返回-1,从原程序的调用点接着往下执行。
可以使用命令:man 3 exec查看函数的具体描述:

#include <unistd.h>

    int execl(const char *path, const char *arg, ...);
       int execlp(const char *file, const char *arg, ...);
       int execle(const char *path, const char *arg, ...);
       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[]);    //这个函数在第二章--man 2 execve


下面介绍两个比较常用的函数:
    int execl(const char *path, const char *arg, ...);
        参数:
            - path:需要指定执行文件的路径或名称(推荐使用绝对路径)
            - arg:是执行可执行文件所需要的列表
                第一个参数一般没什么作用,为了方便,一般写的实质性程序的名称
                从第二个参数往后,就是程序所需要的参数列表
                参数最后需要以NULL结尾(哨兵)
            
        返回值:
            只有当程序调用失败后,才会有返回值,返回-1,并设置error
            如果调用成功,没有返回值



    int execlp(const char *file, const char *arg, ...);
        - 会到环境变量中查找指定的可执行文件,如果找到了就执行,找不到就执行不成功
        参数:
            - file:需要执行的可执行文件的文件名
                a.out
                ps
                pwd
            - arg:是执行可执行文件所需要的列表
                第一个参数一般没什么作用,为了方便,一般写的实质性程序的名称
                从第二个参数往后,就是程序所需要的参数列表
                参数最后需要以NULL结尾(哨兵)
            
        返回值:
            只有当程序调用失败后,才会有返回值,返回-1,并设置error
            如果调用成功,没有返回值

下面是execl()函数和execlp()函数的简单使用案例:

#include <unistd.h>
#include <iostream>

using std::cout;
using std::endl;

namespace execl_test{
    void test01(){
        
        //创建一个子进程,在子进程中执行exec函数族中的函数
        pid_t pid = fork();

        if(pid > 0){
            //父进程
            cout << "I am parent process,pid:"<<getpid()<<endl;
            sleep(1);   //防止孤儿进程
        }
        else if(pid==0){
            //子进程
            cout << "I am child process,pid:"<<getpid()<<endl;

            //执行一个可执行文件
            //execl("hello","hello",NULL);

            //或者执行shell命令
            //execl("/bin/pwd","pwd",NULL);
            execl("/bin/ps","ps","aux",NULL);

            //成功进入可执行文件后这行代码不会被执行
            cout << "I am child process again"<<endl;


        }
    }
}

namespace execlp_test{

    void test01(){
        //创建一个子进程,在子进程中执行exec函数族中的函数
        pid_t pid = fork();

        if(pid > 0){
            //父进程
            cout << "I am parent process,pid:"<<getpid()<<endl;
            sleep(1);   //防止孤儿进程
        }
        else if(pid==0){
            //子进程
            cout << "I am child process,pid:"<<getpid()<<endl;

            //执行一个可执行文件
            //execlp("/home/coder/linux/leason19/hello","hello",NULL);

            //或者执行shell命令
            //execlp("pwd","pwd",NULL);
            execlp("ps","ps","aux",NULL);

            //成功进入可执行文件后这行代码不会被执行
            cout << "I am child process again"<<endl;
    }
}
}

int main(){

    //execl_test::test01();
    execlp_test::test01();
    return 0;
}

下面做一些补充,关于exec函数的后缀单词的介绍:

  • l(list) 参数地址列表,以空指针结尾
  • v(vector) 存有各参数地址的指针数组
  • p(path) 按PATH环境变量指定的目录搜索可执行文件
  • e(enviroment) 存有环境变量字符串地址的指针数组
    简单介绍:
int execv(const char *path, char *const argv[]);
            argv是需要参数的字符串数组
            例如:
                char* argc[]={"ps","aux",NULL};
                execv("/bin/ps",argv);
        int execve(const char *filename, char *const argv[], char *const envp[]);
            例如:
                char* envp[] = {"home/coder/aaa","home/coder/bbb","home/coder/ccc"};
                execve("hello",envp);

End