进程替换详解

目录

1、进程替换现象

2、如何理解

3、exe*系列函数

(1)execl

(2)execlp

  (3)execle

(4)execv

(5)execvp

(6)execvp

4、传环境变量


1、进程替换现象

exec*函数作用:进程代码使用exec*函数,可以执行新的程序

例如下述一个简单的实例:

#include<unistd.h>
#include<iostream>
#include<stdio.h>
int main() {
    char *args[] = {"/bin/ls", "-l", nullptr};  // ls -l 命令
    execvp(args[0], args);  // 执行 ls -l,并替代当前进程
    
    // 如果execvp返回,表明出现了错误
    perror("execvp");
    return 1;
}

对应的makefile文件:

myprocess:myprocess.c
	g++ -o myprocess myprocess.c -std=c++11

.PHNOY:clean
clean:
	rm -f myprocess

执行结果:

2、如何理解

进程 = 内核数据结构 + 代码和数据
继承替换的本质是替换代码和数据,而没有修改内核数据结构

这个过程要融合冯诺伊曼体系结构进行理解:

这个过程叫做,进程的程序替换
同时,这个过程并没有创建新的进程
也就是说,用老进程的壳,执行新的代码和数据
而站在别替换程序的角度来说,就是该程序被加载到内存了
所以,exec*函数,可以是视为一种加载函数
把外设的数据搬到内存中

同时,exec*系列的函数,执行完毕后,后续的代码和数据被替换了
excel函数的返回值不关心
只要替换成功,就不会向后继续运行
只要继续运行,就说明替换失败

子进程在进行程序替换时,为了确保独立性
子进程的数据和代码都会发生写时拷贝

3、exe*系列函数

l:list列表

v:vector数组

p:path路径

e:env环境变量

(1)execl

execl(const char *path, const char *arg, ...);

l是list列表

第一个参数path:执行的程序需要带路径,怎么找到程序
第二个参数:命令行中怎么执行,就怎么传参
例如:ls -a - l
替换时:

execl("/usr/bin/ls","ls","-a","-l",NULL);//当参数列表结束,必须一NULL结尾

第一个参数:你想执行谁,路径,解决的是找到的问题
第二个参数:你想怎么执行,解决的是如何解决的问题

(2)execlp

  • execlp(const char *file, const char *arg, ...):

    • 函数原型:int execlp(const char *file, const char *arg, ...)
    • 功能:从系统的路径变量中查找可执行文件并执行。
    • 参数:
      • file:要执行的程序的名称,不带路径。
      • arg...:可变参数列表,表示要传递给新程序的命令行参数。参数列表必须以 NULL 结束。
    • 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。

  (3)execle

  • execle(const char *path, const char *arg, ..., char * const envp[]):

    • 函数原型:int execle(const char *path, const char *arg, ..., char * const envp[])
    • 功能:执行指定路径的可执行文件,并指定环境变量。
    • 参数:
      • path:要执行的程序的路径。
      • arg...:可变参数列表,表示要传递给新程序的命令行参数。参数列表必须以 NULL 结束。
      • envp:环境变量数组,用于设置新程序的环境变量。数组必须以 NULL 结束。
    • 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。

(4)execv

  • execv(const char *path, char *const argv[]):

    • 函数原型:int execv(const char *path, char *const argv[])
    • 功能:执行指定路径的可执行文件,通过数组传递命令行参数。
    • 参数:
      • path:要执行的程序的路径。
      • argv:参数数组,第一个元素是程序名,后续元素是命令行参数,必须以 NULL 结束。
    • 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。

(5)execvp

  • execvp(const char *file, char *const argv[]):

    • 函数原型:int execvp(const char *file, char *const argv[])
    • 功能:从系统的路径变量中查找可执行文件并执行,通过数组传递命令行参数。
    • 参数:
      • file:要执行的程序的名称,不带路径。
      • argv:参数数组,第一个元素是程序名,后续元素是命令行参数,必须以 NULL 结束。
    • 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。

(6)execvp

  • execve(const char *path, char *const argv[], char *const envp[]):

    • 函数原型:int execve(const char *path, char *const argv[], char *const envp[])
    • 功能:执行指定路径的可执行文件,通过数组传递命令行参数,并指定环境变量。
    • 参数:
      • path:要执行的程序的路径。
      • argv:参数数组,第一个元素是程序名,后续元素是命令行参数,必须以 NULL 结束。
      • envp:环境变量数组,用于设置新程序的环境变量。数组必须以 NULL 结束。
    • 返回值:如果调用成功,该函数不会返回,因为当前进程的映像被替换。

4、传环境变量

原来我们说过,bash创建一个子进程的时候
首先bash会有一张命令行参数表和环境变量表
通过某种方式传递给子进程
那么是通过什么方式呢?
就是通过execvpe这个函数
int execvpe(const char *file, char *const argv[], char *const envp[]);
argv就是命令行参数表,envp就是环境变量表
环境变量的参数,如果传的是自定义的,那么就会全部替换为自定义后的环境变量

传环境变量的规则:

1、新的环境变量,自己构建,这样会全部替换bash的环境变量
2、老的环境变量,(bash)extern char** envion
3、putenv(“xxx = xxx”)新增环境变量表,只是新增,而不是全部替换

本质上,7个函数只有execve这个系统调用
其他函数都是这个系统调用的封装

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

二十5画生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值