Linux进程替换:exec函数族

引入

        如何在某进程内部启动一个外部程序,由内核将该外部程序读入内存,使其执行成为一个进程?

        使用exec函数族实现。


exec函数族

#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[]);

int execve(const char* filename, char* const argv[], char* const envp[]);
/*
只有execve是真正意义上的系统调用,其他都是在此基础上包装过的库函数

功能:
    根据文件名file找到可执行文件来取代调用进程的内容,即在调用进程内部执行一个可执行文件。

    进程调用exec函数时,该进程完全由新程序替换,新程序从其main函数开始执行。
    调用exec函数不会创建新进程,因此进程pid、父进程号、进程组号、当前工作目录不会改变。
    exec只是用一个新程序替换当前进程的正文、数据、堆栈。
参数:
    path:可执行程序的完整路径名;若不以/开头,则会到当前工作目录查找;
    file:可执行程序文件名,若不以/开头,则会根据PATH环境变量查找。
    envp:传递给新程序环境变量数组,必须以NULL结尾。若无此参数,则新程序会继承原程序的环境变量。
返回值:
    成功:不会返回,因为进程地址空间已被新程序替换;
    失败:-1,并设置errno
*/

exec进程替换示意图

execlp使用示例1,使用进程回收示例程序替换当前程序:

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

int main(void) {
    printf("Before exec.\n");

    /*
        int execlp(const char* file, const char* arg, .../* (char*) NULL*/);
        file是可执行程序文件名,若不以/开头,则会根据PATH环境变量查找,
        arg0是可执行程序名;
        arg1及后面是可执行文件的参数;
        最后一个参数是NULL;
    */
    execlp("./a.out", "./a.out", NULL);  // a.out为进程回收示例程序

    printf("After exec.\n"); // 不会执行,因为被替换了
    return 0;
}

运行结果:


execlp使用示例2,使用ls -l /home命令替换:

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

int main(void) {
    printf("Before exec.\n");

    /*
        int execlp(const char* file, const char* arg, .../* (char*) NULL*/);
        file是可执行程序文件名,若不以/开头,则会根据PATH环境变量查找,
        arg0是可执行程序名;
        arg1及后面是可执行文件的参数;
        最后一个参数是NULL。
    */
    execlp("ls", "ls", "-l", "/home", NULL); // 等价于ls -l /home

    printf("After exec.\n"); // 不会执行,因为被替换了
    return 0;
}

运行结果:

执行到exec函数,使用其中指定的可执行程序将原程序全部替换,并从新程序的主函数执行,所以原程序中exec的后续程序不会执行。


execl使用示例:

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

int main(void) {
    printf("Before exec.\n");
    /*
        int execl(const char* path, const char* arg, .../* (char*) NULL*/);
        path是可执行程序的绝对路径或相对路径;
        arg0是可执行程序名;
        arg1及后面是可执行文件的参数;
        最后一个参数是NULL。
    */
    execl("/bin/ls", "ls", "-l", "/home", NULL);

    printf("After exec.\n"); // 不会执行,因为被替换了
    return 0;
}

运行结果:


execv使用示例:

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

int main() {
    printf("before exec.\n");
    
    char* argv[] = { "ls", "/home", NULL }; // execv的第二个参数
    execv("/bin/ls", argv);
    
    printf("after exec");
    return 0;
}

运行结果:


execvp使用示例:

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

int main() {
    printf("before exec.\n");
    
    char* argv[] = { "ls", "/home", NULL }; // execvp的第二个参数
    execvp("ls", argv);
    
    printf("after exec");
    return 0;
}

运行结果:


execle示例:

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

int main() {
    printf("before exec.\n");

    char* argv[] = { "ls", "/home", NULL }; // execvp的第二个参数
    char* envp[] = { "ADDR=BEIJING",NULL }; // 环境变量指针数组

    execle("/bin/ls", "ls", "-l", "/home", NULL, envp);

    printf("after exec");
    return 0;
}

运行结果: 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的马师兄

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值