进程程序替换

进程程序替换并没有创建新的进程
怎么样才算是新建了一个进程?
创建好task_struct,再把task_struct插到双向链表里面,这才是创建好了一个进程。

所谓的进程程序替换就是把物理内存上的数据和代码替换成了另外一个磁盘上的可执行文件的数据和代码,说白了,我们前面写的一些程序都是把它编译成一个可执行程序,一个可执行文件,而这个可执行文件非得是通过“./文件名”的方式才能把它运行起来,这样一个运行的过程其实就是由操作系统把这个文件里面包含的数据和代码加载到内存中的过程,进程程序替换它的这个替换和运行一个程序它的一个加载过程是非常类似的,意思是我们本来就有一个进程,然后这样一个进程它有自己的代码和数据,但是我想借助这个进程能够去执行另外一个可执行文件中的代码,就可以通过程序替换的方式来完成这一项操作。
所以说,进程程序替换是将原有进程的代码和数据替换成新的可执行程序的代码和数据。
在这里插入图片描述
exec函数族头文件都是unistd.h
如果调用成功则加载新的程序从启动代码开始执行,不再返回;如果调用出错则返回 -1。
1、execl(l指list,可变参数列表)
int execl(const char *path, const char *arg, …);
其中,参数1表示路径,就是你要替换的那个可执行程序的那个可执行文件它的路径是什么;
后面是一个变长参数列表,表示你要替换的那个可执行程序在启动的时候要加上哪些的命令行参数。
由于行参数到底有几个这个不确定,所以通过变长参数列表的形式来提供给我们用户使用。

2、execlp(p表示的含义叫做环境变量PATH,表示PATH这个环境变量),p特指环境变量中的PATH,只是环境变量中的一个。
int execlp(const char *file, const char *arg, …);
PATH里面的内容是一组路径,这组路径是用来,当我们在终端下敲下一个指令的时候,其实是要运行一个可执行文件,那这可执行文件在哪个目录下去查找它,就在PATH包含的路径中去查找。
execlp意思是你在告诉程序调用哪一个可执行文件的时候,你不需要写全路径,只写文件名就可以。
其中,参数1只写一个文件名就行,文件名怎么映射到具体的完整路径上,自动地从PATH中进行查找。只要告诉文件名,就能自动地找到它的路径。如果这个文件不在 PATH 下,那就需要指定路径了,相对路径或者绝对路径均可以。

3、execle(e表示的叫做环境变量),e代表着整体环境变量这个大的概念。
int execle(const char *path, const char *arg, … , char *const envp[]);
借助这个函数,可以让调用者去手动设置即将要替换好的这个程序它的环境变量应该长成什么样子,所以有envp[ ]这个参数,这样的一个参数里面就包含了若干的环境变量,那也就是说在调用这个函数的时候,就可以手动构造出一个环境变量的数组来,然后把这个数组配置进去,那么当进程程序替换完毕后,替换好的进程它的环境变量表就变成了刚刚配置好的这样一个内容,即允许用户手动设置环境变量。

4、execv(v表示vector,数组)
int execv(const char * path, char *const argv[]);
execv这三个函数都是通过argv[ ]的形式来组织若干个命令行参数的

5、int execvp(const char *file, char *const argv[]);

6、execve是系统调用,其余5个都是库函数,都是基于execve系统调用来实现的。
man第一页是用户指令,第二页是系统调用,第三页是库函数。
int execve(const char *path, char *const argv[], char *const envp[]);

在这里插入图片描述
在这里插入图片描述

<think>我们正在讨论Linux系统中的进程程序替换。根据引用[2],进程程序替换是指子进程执行全新的程序,不再执行父进程的代码。引用[3]展示了一个使用execl函数进行程序替换的例子。原理上,当调用exec系列函数时,当前进程的代码和数据被新程序的代码和数据替换,但进程ID保持不变。引用[1]和[4]也提到了进程程序替换的概念和函数使用。具体来说,进程程序替换的工作原理如下:1.调用exec函数(如execl、execv等)后,操作系统会加载指定的新程序到当前进程的内存空间。2.新程序替换当前进程的代码段(text)、数据段(data)、堆(heap)和栈(stack)等。3.进程ID(PID)保持不变,因此替换后仍然是同一个进程,但执行的是全新的程序。4.如果exec函数调用成功,则不会返回(因为原程序的代码已被替换),只有调用失败时才会返回错误。例如,在引用[3]的代码中:```cexecl("/usr/bin/ls","ls","-l","-a",NULL);```调用execl后,当前进程将执行`/usr/bin/ls`程序,并传递参数"ls","-l","-a"。注意事项(引用[4]):-exec系列函数只有调用失败时才返回,所以成功时后面的代码不会执行。-新程序从main函数开始执行。-环境变量可以通过exec函数传递(如execle、execvpe等)。常见的exec函数族包括:-execl:参数以列表形式传递(可变参数)。-execv:参数以数组形式传递。-execlp、execvp:使用PATH环境变量查找程序。-execle、execvpe:可传递环境变量。例如,使用execvp:```cchar*argv[]={"ls","-l","-a",NULL};execvp("ls",argv);```总结:进程程序替换通过exec系列函数实现,它替换当前进程的映像为新的程序映像,但保持进程ID不变,从而实现让子进程执行与父进程完全不同的程序。§§相关问题§§1.在Linux中,exec函数族有哪些常见函数?它们有什么区别?2.进程程序替换后,原进程打开的文件描述符会如何处理?3.如何传递环境变量给新程序?4.为什么exec函数调用成功不会返回?5.进程程序替换和创建新进程(fork)有什么区别和联系?</think>### Linux 进程程序替换的工作原理 在 Linux 系统中,**进程程序替换**是指在不创建新进程的前提下,将当前进程执行的程序完全替换为新程序的技术。其核心原理是通过 `exec` 函数族实现,具体工作原理如下: #### 1. **内存空间替换(核心机制)** - 当调用 `exec` 函数(如 `execl()`)时,操作系统会**清空当前进程的代码段、数据段和堆栈**。 - 新程序的代码和数据从磁盘加载到内存,覆盖原进程的内存空间: ```c execl("/usr/bin/ls", "ls", "-l", "-a", NULL); // 替换为 ls 程序 ``` - 进程 ID(PID)保持不变,但执行的指令和数据完全更新[^2][^3]。 #### 2. **执行流程重置** - 新程序从 `main()` 函数开始执行,原程序的执行流被永久中断。 - 若替换成功,`exec` 函数**不会返回**(原程序代码已被清除);失败时才返回错误码[^3][^4]。 #### 3. **资源继承与处理** - **保留的资源**: - 进程 PID、父进程 PID - 文件描述符(除非显式设置 `FD_CLOEXEC`) - 工作目录、信号处理设置 - **重置的资源**: - 挂起的信号被清除 - 内存锁(`mlock`)被释放 - 线程局部存储被销毁[^2][^4] #### 4. `exec` 函数族的分工 | 函数 | 参数传递方式 | 是否搜索 PATH | 环境变量处理 | |-------------|-------------------|---------------|-----------------| | `execl()` | 参数列表 (可变参数) | ❌ | 继承父进程 | | `execv()` | 参数数组 | ❌ | 继承父进程 | | `execvp()` | 参数数组 | ✅ | 继承父进程 | | `execle()` | 参数列表 | ❌ | 自定义环境变量 | > 示例:`execvp("ls", (char*[]){"ls", "-l", NULL})` 自动搜索 `PATH` 中的 `ls`[^4] #### 5. **与 `fork()` 的协同工作** 典型用法是先 `fork()` 创建子进程,再在子进程中调用 `exec()`: ```c pid_t pid = fork(); if (pid == 0) { // 子进程 execl("/bin/ls", "ls", NULL); perror("exec failed"); // 仅 exec 失败时执行 exit(1); } else { // 父进程 waitpid(pid, NULL, 0); } ``` 这种组合实现了**创建新进程并执行不同程序**的能力[^2][^3]。 #### 关键特点总结 - **零进程创建开销**:仅替换内存内容,不创建新进程 - **原子性**:替换操作不可中断,要么完全成功要么失败 - **环境可控**:可通过 `execle()` 等函数定制新程序的环境变量 - **失败回退**:若替换失败(如路径错误),原进程继续执行后续代码[^3][^4] > 应用场景:Shell 命令执行(如 `bash` 执行 `ls`)、守护进程重启自身、安全沙盒等[^1][^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值