IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【Linux】进程控制(四):进程程序替换 exec 函数簇 -> 正文阅读

[系统运维]【Linux】进程控制(四):进程程序替换 exec 函数簇

【Linux】进程控制(四):进程程序替换 exec 函数簇


一、进程程序替换

1.1 概念

??用 fork 创建子进程后执行的是和父进程相同的程序,此时子进程就需要进程程序替换,进程程序替换就是将已经跑起来的进程替换成执行其它程序的进程,也就是说该进程的用户空间代码和数据完全被新程序替换,子进程从新程序的启动历程开始执行。


1.2 原理

image-20210708173726222

??替换函数将正在执行的进程的进程虚拟地址空间里的代码段和数据段替换成新的程序,当前在执行的进程就会执行替换之后的程序代码,并且堆区和栈区都需要更新。


1.3 为什么要进程程序替换

??守护进程先启动,创建一个子进程,让子进程程序替换成为另一个程序,实现不同的一个功能,父子进程会进行通信,实现 “当子进程异常退出时,守护进程就会重新拉起子进程”。(但不能说守护进程一定能够解决子进程异常退出的问题,异常退出可能是子进程的程序代码存在一定的问题)

??我们常用的 shell 命令行解释器,就是采用的进程程序替换的原理。


二、进程替换接口

??exce 函数簇: 它不是一个函数,而是一堆函数。(execl 、execlp、execle、execv、execvp、execve)

#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 *file, char *const argv[],char *const envp[]);   //系统调用

2.1 execl 函数

#include <unistd.h>
//库函数
int execl(const char *path, const char *arg, ...); 

参数:

??path: 带路径的可执行程序,即替换的可执行程序的路径和名称

??arg: 给可执行程序传递的参数(传递的第一个参数必须是可执行程序的名称,后面依次传递,中间以 “逗号” 隔开,最后以 “NULL” 结束)

返回值:

??替换成功,没有返回值;替换失败,返回小于 0 的值,仍旧执行当前的程序代码。

验证:

??shift 程序替换 execl 程序

//execl.c
#include<unistd.h>
#include<stdio.h>
int main()
{
    printf("---begin---\n");
    printf("i am execl\n");

    execl("./shift","shift",NULL); //进程程序替换
    
    printf("---end---\n");

    return 0;
}
//shift.c
#include <stdio.h>
int main()
{
    int count = 5; 
    printf("---repalce---\n");
    while(count--)
    {
        printf("i am shift\n");
    }

    return 0;
}

??可以看到进程程序替换成功,execl 程序执行 i am execl 后,去运行 shift 程序了,和之前的程序就没有关系了,也不会打印 ---end---

在这里插入图片描述

??如果将 shift 可执行程序移动到上级目录,和 execl 函数中 path 路径不一致。可以看到进程程序替换失败,打印 ---end--- 后 execl 程序从 return 返回。

在这里插入图片描述

??使用 which ls 查看到 ls 可执行程序的路径为 /usr/bin/ls。我们使用 ls 程序来替换 execl 程序。

 execl("/usr/bin/ls","ls","-a",NULL); //进程程序替换

??可以看到 execl 程序执行 i am execl 后,去运行 ls 程序了。我们的可执行程序是 ls,传递的参数是 -a , 可以看到它和 ls -a 执行的效果是一样的,只是我们使用的进程程序替换后的结果没有高亮显示。

image-20210709115000706


2.2 execlp 函数

#include <unistd.h>
//库函数
int execlp(const char *file, const char *arg, ...); 

参数:

??file: 替换的可执行程序的名称(替换的可执行程序必须是在 PATH 环境变量当中可以找到的,也就是说待替换的可执行程序需要能被操作系统找到。这里也可以传递带路径的可执行程序)

??arg: 给可执行程序传递的参数(传递的第一个参数必须是可执行程序的名称,后面依次传递,中间以 “逗号” 隔开,最后以 “NULL” 结束)

返回值:

??替换成功,没有返回值;替换失败,返回小于 0 的值。

验证:
??pwd 程序替换 execlp 程序

//execlp.c
#include<unistd.h>
#include<stdio.h>
int main()
{
    printf("---begin---\n");
    
    execlp("pwd","pwd",NULL); //进程程序替换
    
    printf("---end---\n");
    return 0;
}

??可以看到进程程序替换成功, execlp 程序执行 ---begin--- 后,在 PATH 环境变量中找 pwd 路径去运行 pwd 程序了。

在这里插入图片描述


??带 p 和不带 p : 如果 exec 函数当中带有 p,则表示会搜索环境变量,并且第一个参数传入可执行程序的名称即可。不带 p,则表示不会搜索环境变量,所以需要传递带路径的可执行程序。


2.3 execle 函数

#include <unistd.h>
//库函数
int execle(const char *path, const char *arg,..., char * const envp[]); 

参数:

??path: 带路径的可执行程序。

??arg: 给可执行程序传递的参数(传递的第一个参数必须是可执行程序的名称,后面依次传递,中间以 “逗号” 隔开,最后以 “NULL” 结束)

??envp: 程序员自己组织的环境变量,如果不传入,则认为当前替换之后的程序没有环境变量。

返回值:

??替换成功,没有返回值;替换失败,返回小于 0 的值。


??带 e 和不带 e : 如果 exec 函数当中带有 e,则需要自己组织环境变量。不带 e,则不需要程序员自己组织环境变量。


2.4 execv 函数

#include <unistd.h>
//库函数
int execv(const char *path, char *const argv[]); 

参数:

??path: 带路径的可执行程序。

??argv: 给可执行程序传递的参数(数组的第一个参数是可执行程序的名称,最后一个参数是 “NULL”)

返回值:

??替换成功,没有返回值;替换失败,返回小于 0 的值。

验证:

??ls 程序替换 execv 程序

//execv.c
#include<stdio.h>
#include<unistd.h>
int main()
{
    printf("---begin---\n");
    char * argv[10];
    argv[0] = "ls";
    argv[1] = "-l";
    argv[2] = "..";
    argv[3] = NULL;
    
    execv("/usr/bin/ls",argv); //进程程序替换
    
    printf("---end---\n");
    return 0;
}

??可以看到进程程序替换成功, execv 程序执行 ---begin--- 后,去运行 ls 程序了。我们传递的参数是 -l.. ,可以看到它和 ls -l .. 执行的效果是一样的,都是显示上级目录的文件详细信息。

在这里插入图片描述


??带 l 和不带 l: 如果 exec 函数当中带有 l,则表示参数是可变参数列表的形式。不带 l,则表示参数是字符指针数组的形式。

??带 v 和不带 v: 如果 exec 函数当中带有 v,则表示参数是以字符指针数组的形式传递给 exec 函数的,进而传递给待替换的可执行程序。不带 v,则表示参数是可变参数列表的形式。


2.5 execvp 函数

#include <unistd.h>
//库函数
int execvp(const char *file, char *const argv[]); 

参数:

??file: 替换的可执行程序的名称。

??argv: 给可执行程序传递的参数(数组的第一个参数是可执行程序的名称,最后一个参数是 “NULL”)

返回值:

??替换成功,没有返回值;替换失败,返回小于 0 的值。


2.6 execve 函数

#include <unistd.h>
//系统调用
int execve(const char *file, char *const argv[],char *const envp[]); 

参数:

??file: 替换的可执行程序的名称。

??argv: 给可执行程序传递的参数(数组的第一个参数是可执行程序的名称,最后一个参数是 “NULL”)

??envp: 程序员自己组织的环境变量,如果不传入,则认为当前替换之后的程序没有环境变量。

返回值:

??替换成功,没有返回值;替换失败,返回小于 0 的值。

验证:

?? ls 程序替换 execve 程序

//execve.c
#include<stdio.h>
#include<unistd.h>
int main()
{
    char * argv[10];
    argv[0] = "ls";
    argv[1] = "-l";
    argv[2] = "..";
    argv[3] = NULL;
	
	char * envp[10];
	envp[0] = "PATH=/usr/bin";
	envp[1] = NULL;

	execve("/usr/bin/ls",argv,envp); //进程程序替换

    return 0;
}

??可以看到进程程序替换成功,可以看到它和 ls -l .. 执行的效果是一样的,都是显示上级目录的文件详细信息。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mGRVIPQ9-1625828762975)(../AppData/Roaming/Typora/typora-user-images/image-20210709181250771.png)]

三、总结

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[]);   //系统调用

??(1)带 l 和不带 l:

??如果 exec 函数当中带有 l,则表示参数是可变参数列表的形式。不带 l,则表示参数是字符指针数组的形式。


??(2)带 v 和不带 v:

??如果 exec 函数当中带有 v,则表示参数是以字符指针数组的形式传递给 exec 函数的,进而传递给待替换的可执行程序。不带 v,则表示参数是可变参数列表的形式。


??(3)带 p 和不带 p :

??如果 exec 函数当中带有 p,则表示会搜索环境变量,并且第一个参数传入可执行程序的名称即可。不带 p,则表示不会搜索环境变量,所以需要传递带路径的可执行程序


??(4)带 e 和不带 e :

??如果 exec 函数当中带有 e,则需要自己组织环境变量。不带 e,则不需要程序员自己组织环境变量。


??规律:

????l (list) 表示参数采用可变参数列表

????v (vector) 表示参数采用字符指针数组

????p (path) 表示自动搜索环境变量 PATH

????e (env) 表示自己维护环境变量


在这里插入图片描述

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 11:42:18  更:2021-07-10 11:42:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 0:39:05-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码