Linux:进程程序替换

上篇文章:Linux:进程控制(创建/终止/等待/获取退出信息/多进程)


目录

1.阅读程序替换代码

1.1execl

2.替换原理

3.父子进程版本

4.使用举例

六处细节

5.替换函数

5.1execv

5.2execlp

5.3execvp

5.4execle

5.5execve

思考

6.拓展

6.1putenv


1.阅读程序替换代码

fork()之后,父子各自执行父进程代码的一部分,如果子进程想执行一个全新的程序,就要通过进程的程序替换来完成。

程序替换是通过特定的接口,加载磁盘上的一个全新的程序(代码和数据),加载到调用进程的地址空间中。

运行结果:

1.1execl

2.替换原理

用fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。调用exec并不创建新进程,所以调用exec前后该进程的id并不改变。

总结:程序替换是只替换代码和数据,不创建新进程,而是让进程执行一份全新的代码。所以它的pid并不会改变。

而当使用fork()函数,让子进程程序通过程序替换时,由于进程具有独立性,那么就会发生写时拷贝,父子两个进程会彻底的独立。

观察上述的运行结果,我们发现它并没有打印最后一句,原因是程序替换一旦成功,就没有返回值,如果有返回值,就是替换失败。

3.父子进程版本

通过上述代码,可以让子进程完成一个全新的任务,而这,不就是bash的工作原理吗?我们这里的父进程就相当于bash。

4.使用举例

l表示参数使用列表

六处细节

1.省略输入有时候也能运行,但是不建议

2.path:不建议省略路径,写绝对或者相对路径

3.我们自己写的程序也能被替换->如果当前进程不fork子进程,execl就是加载程序到内存的过程->execl就是加载器的底层接口

4.程序替换并没有创建新进程

示例:

5.父进程或者OS传递给子进程的是通过系统调用exec*传递给子进程的

6.通过上述示例,可以看出我们通过系统调用,让进程以全新的程序进行,所以也可以通过C语言调用C++,shell,python,java这类语言->最终原因是因为其本质都是进程

以shell脚本为例:

修改myexec.c

以python脚本为例:

5.替换函数

前提认识:

要执行一个程序,其首先时找到特定路径下的文件,之后再根据文件或选项进行执行,例如执行ls命令,应该是先找到它的路径再做选择:

有七种以exec开头的函数,统称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, ...,char *const envp[]);
int execv(const char *path, char *const argv[]);
int execvp(const char *file, char *const argv[]);
int execve(const char *path, char *const argv[], char *const envp[]);
int execvpe(const char *file, char *const argv[],char *const envp[]);

5.1execv

复制代码
int execv(const char *path, char *const argv[]);

此函数后面的参数使用的是指针数组传参,可以以数组的形式调用某些函数。

这里的v指vector

5.2execlp

复制代码
int execlp(const char *file, const char *arg, ...);

p指PATH,只需要传递可执行文件名,execlp会自动到环境变量PATH中查找可执行程序。

5.3execvp

复制代码
int execvp(const char *file, char *const argv[]);

5.4execle

e(environ):表示自己维护环境变量(自定义环境变量)

复制代码
int execle(const char *path, const char *arg, ...,char *const envp[]);

我们自己创建环境变量:

**结论:**进程程序替换的时候,即使我们没有显示的传递环境变量表的信息,但是子进程依旧能够通过main(char *env[])获得默认的环境变量。

我们也可以使用系统默认的环境变量:

5.5execve

复制代码
int execve(const char *path, char *const argv[], char *const envp[]);

execve()是一个真正的系统调用,操作系统提供的程序替换系统调用,就这一个函数。

EXEC(3)是库函数

而上方的库函数最终会转换为execve,所以进程程序替换的时候,即使我们没有显示的传递环境变量表的信息,但是子进程依旧能够通过main(char *env[])获得默认的环境变量。

思考

那么针对execve为什么要生成这么多的封装呢?

因为它的接口形参设置上比较麻烦,要求参数全部设为数组,但我们所面对的环境变量不一定全为数组设置,所以为了满足不同的应用场景才产生如此多的封装。

6.拓展

在保留旧的环境变量的同时,新增几个环境变量

6.1putenv

putenv是指在当前进程的环境变量表中,新增一组环境变量

结果:

本章完。

相关推荐
祁鱼鱼鱼鱼鱼3 小时前
Keepalived实验环境设定
linux·服务器·网络
Genie cloud4 小时前
VPS 网络连接故障诊断与排查实用指南
linux·服务器·ssh
RisunJan4 小时前
Linux命令-lnstat(快速查找文件和目录)
linux·运维·服务器
滴水之功4 小时前
OpenWrt的WAN和LAN的切换
linux·网络·openwrt
lihui_cbdd4 小时前
Slurm 集群内存管理与限制配置
运维·服务器
历程里程碑4 小时前
Linux 17 程序地址空间
linux·运维·服务器·开发语言·数据结构·笔记·排序算法
CC.GG4 小时前
【Linux】进程控制(二)----进程程序替换、编写自主Shell命令行解释器(简易版)
linux·服务器·数据库
数研小生5 小时前
Full Analysis of Taobao Item Detail API taobao.item.get
java·服务器·前端
H Journey5 小时前
Linux 下添加用户相关
linux·运维·服务器·添加用户