exec族函数

本节学习exec族函数,并大量参考了以下链接:

linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客

exec族函数函数的作用

我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变

同时,由于exec族函数包含很多API,所以一个个去Linux敲man可能有些麻烦,可以直接去Linux官网的man Page来查看:Linux man pages

 

exec族函数中的具体函数介绍

exec族函数功能

  • 在进程内部调用执行一个可执行文件。可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。

函数族成员

  • execl
  • execlp
  • execle
  • execv
  • execvp
  • execvpe

函数原型

#include <unistd.h>
extern char **environ;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 execvpe(const char *file, char *const argv[],char *const envp[]); //应用相对较少

参数说明 

  • path:可执行文件的路径名字
  • arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
  • file:如果参数file中包含/,则就将其视为路径名,否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件
  • 返回值:exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行

exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:

  • l : 使用参数列表
  • p:使用文件名,并从PATH环境进行寻找可执行文件
  • v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
  • e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

带 “l” 的一类exec函数(l表示list)

包括execlexeclpexecle,要求将新程序的每个命令行参数都说明为 一个单独的参数。这种参数表以空指针结尾

通过execl举例:

execl.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execl("./arg_go","aaa","bbb",NULL) == -1){printf("execl failed!\n");perror("why"); //用于判断错误}printf("after execl\n");return 0;
}

arg.c:

#include <stdio.h>int main(int argc,char *argv[])
{int i = 0;for(i = 0; i < argc; i++){printf("argv[%d]: %s\n",i,argv[i]); }return 0;
}

实现效果1:

可见,在运行了execl函数之后,程序确实被完全替代成了另一个程序,所以原程序最后的“after execl”并不会被打印!

同时再次强调,execl函数的第一个参数,写的是执行文件,而不是C文件,所以,运行主程序之前,先编译并自己命名一个执行文件!

那么既然execl可以使用可执行程序完全替换一段程序,那么系统的指令本质上也是一个个可执行文件,就比如经常使用的 “ls” ,通过“whereis ls”可以查看这个可执行文件的绝对路径:

修改execl.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execl("/bin/ls","ls","-l",NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

实现效果2:

可见,通过execl函数,成功将原程序替换成了ls,并且还附带了“-l” 的参数

 

带 “p” 的一类exec函数

包括execlpexecvpexecvpe,如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。举个例子,PATH=/bin:/usr/bin

通过execlp举例:

execlp.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execlp("ls","ls","-l",NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

实现效果:

可见,实现了和上面使用execl来替换“ls”相同的效果,但是代码却有所区别,execlp的第一个参数不需要输入绝对路径,只需要输入可执行文件的名字就可以,其原因就是execlp的第一个参数不是path而是file,而file参数如同上面所说: “如果参数file中包含/,则就将其视为路径名,否则就按PATH环境变量,在它所指定的各目录中搜寻可执行文件 

为了进一步对比区别,可以将execl.c的代码中的这一句进行修改,第一个参数也改成“ls”:

 if(execl("ls","ls","-l",NULL) == -1)

然后运行execl.c

 

显然,这再次说明了对于execl来说,这种直接写可执行文件名字的方式不可取

环境变量的概念穿插

另外,此处引出了“环境变量"的概念,在Linux中可以用 “echo $PATH” 来查看环境变量: 

也就是说,只要可执行文件在上图的这些环境变量路径下那么只要调用带 “p” 的exec族函数,第一个file参数就可以直接写可执行文件的名字了

Q:那如何将新的路径配置到环境变量中去?

A:使用export指令:“export PATH=$PATH:想要添加的路径

使用 “pwd” 显示当前路径:

然后使用 “export PATH=$PATH:/home/mjm/JC”  将当前路径添加到环境变量:

此时,如果修改 execlp.c 的代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");if(execlp("arg_go","aaa","bbb",NULL) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

执行代码:

 

 可见,由于此时当前路径被添加到了环境变量中所以使用execlp函数并将第一个参数直接写成当前路径下的可执行文件,也可以成功运行!

带 “v” 不带 “l” 的一类exec函数 

包括execvexecvpexecve,应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数

 通过execv举例:

execv.c:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(void)
{printf("before execl\n");char *argv[] = {"ls","-l",NULL};if(execv("/bin/ls",argv) == -1){printf("execl failed!\n");perror("why");}printf("after execl\n");return 0;
}

可见,唯一的区别就是“先构造了一个指向各参数的指针数组 

实现效果:

可见,同样实现了将“ls”替换原程序的效果,并且也增加了“-l” 的参数

 

带 “e” 的一类exec函数 (应用相对较少)

包括execleexecvpe,可以传递一个指向环境字符串指针数组的指针

由于相对比较复杂且初学时并不常用,所以不做介绍,可以去本节开头的链接去学习相关概念。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/34102.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Fortinet安全专家问答实录|如何防护暴力破解、撞库攻击

黑客攻防&#xff0c;一个看似神秘&#xff0c;但却必不可缺的领域。近期&#xff0c;全球网络与安全融合领域领导者Fortinet&#xff08;Nasdaq&#xff1a;FTNT&#xff09;&#xff0c;开启了Fortinet DEMO DAY系列实战攻防演练线上直播&#xff0c;让人人都能零距离观摩黑客…

AI 绘画Stable Diffusion 研究(六)sd提示词插件

大家好&#xff0c;我是风雨无阻。 今天为大家推荐一款可以有效提升我们使用 Stable Diffusion WebUI 效率的插件&#xff0c; 它就是 prompt-all-in-one&#xff0c; 它不但能直接将 WebUI 中的中文提示词转换为英文&#xff0c;还能一键为关键词加权重&#xff0c;更能建立常…

消息中间件 —— 初识Kafka

文章目录 1、Kafka简介1.1、消息队列1.1.1、为什么要有消息队列&#xff1f;1.1.2、消息队列1.1.3、消息队列的分类1.1.4、p2p 和 发布订阅MQ的比较1.1.5、消息系统的使用场景1.1.6、常见的消息系统 1.2、Kafka简介1.2.1、简介1.2.2、设计目标1.2.3、kafka核心的概念 2、Kafka的…

存储过程的学习

1&#xff0c;前言 这是实习期间学习的&#xff0c;我可能是在学校没好好听课&#xff0c;&#xff08;或者就是学校比较垃&#xff0c;没教这部分&#xff0c;在公司经理让我下去自己学习&#xff0c;太难了&#xff0c;因为是公司代码很多部分都是很多表的操作&#…

菲律宾的区块链和NFT市场调研

菲律宾的区块链和NFT市场调研 基本介绍 参考&#xff1a; https://zh.wikipedia.org/wiki/%E8%8F%B2%E5%BE%8B%E5%AE%BE zheng治制度&#xff1a;Zongtong议会制 现任Zongtong&#xff1a; 小费迪南德马科斯, 是独裁者费迪南德马科斯之子&#xff0c;人称“小马科斯” 官方语言…

【动态map】牛客挑战赛67 B

登录—专业IT笔试面试备考平台_牛客网 题意&#xff1a; 思路&#xff1a; 考虑动态的map 可以先定义一个状态&#xff0c;然后用map统计前缀这个状态的出现次数 在这里&#xff0c;定义{a,b}为cnt1 - cnt0和cnt2 - cnt0 当cnt0 和 cnt1都和cnt2相同时&#xff0c;统计贡献…

oracle 增加控制文件

oracle 增加控制文件 1、看control_file路径 SQL> show parameter controlNAME TYPE VALUE ------------------------------------ ----------- ------------------------------ control_file_record_keep_time integer …

Kubernetes kubectl管理命令使用方法

陈述式资源管理方法&#xff08;通过命令行&#xff09; 1.kubernetes 集群管理集群资源的唯一入口是通过相应的方法调用 apiserver 的接口 2.kubectl 是官方的CLI命令行工具&#xff0c;用于与 apiserver 进行通信&#xff0c;将用户在命令行输入的命令&#xff0c;组织并转化…

从零开始学python(十六)爬虫集群部署

前言 今天讲述Python框架源码专题最后一个部分&#xff0c;爬虫集群部署&#xff0c;前面更新了十五个从零开始学python的系列文章&#xff0c;分别是&#xff1a; 1.编程语法必修篇 2.网络编程篇 3.多线程/多进程/协程篇 4.MySQL数据库篇 5.Redis数据库篇 6.MongoDB数据库篇 …

运维监控学习笔记2

硬件监控&#xff1a; 1&#xff09;使用IPMI 2&#xff09;机房巡检 路由器和交换机&#xff1a; 使用SNMP&#xff08;简单网络管理协议&#xff09;进行监控。 Linux 安装snmp&#xff1a; yum install -y net-snmp net-snmp-utils 说明&#xff1a;net-snmp是安装在snm…

到 2030 年API 攻击预计将激增近 1000%

导读云原生应用程序编程接口管理公司 Kong 联合外部经济学家的最新研究预计&#xff0c;截至 2030 年 API 攻击将激增 996%&#xff0c;意味着与 API 相关的网络威胁的频率和强度都显着升级。 这项研究由 Kong 分析师和布朗大学副教授 Christopher Whaley 博士合作进行&#x…

StarGANv2: Diverse Image Synthesis for Multiple Domains论文解读及实现(一)

StarGAN v2: Diverse Image Synthesis for Multiple Domainsp github:https://github.com/clovaai/stargan-v2 1 模型架构 模型主要架构由四部分组成 ①Generator、②Mapping network、③Style encoder、④Discriminator Generator&#xff1a;G网络 生成模型G将输入图片x转换…

【软件测试】UI自动化框架,数据驱动 vs 关键字驱动怎么选

一、UI自动化测试用例剖析 让我们先从分析一端自动化测试案例的代码开始我们的旅程。以下是我之前写的一个自动化测试的小Demo。这个Demo基于Selenium与Java。 自动化测试小Demo 它要测试的东西其实是要看一下百度搜索能不能返回兴业银行的官网。我们分析一下这段代码都包含些…

清除pip安装库时的缓存

目录 1、命令清除缓存 2、路径手动清除 在使用pip安装Python库时&#xff0c;如果之前已经下载过该库&#xff0c;pip会默认使用缓存来安装库&#xff0c;而不是重新从网络上下载。缓存文件通常存储在用户目录下的缓存文件夹中&#xff0c;具体位置因操作系统和Python版本而异…

项目管理师基础之项目管理计划和项目文件

项目管理过程中&#xff0c;会使用并产生两大类文件&#xff1a;项目管理计划和项目文件。内容一般如下&#xff1a; 整个项目生命周期需要收集、分析和转化大量的数据。从各个过程收集项目数据&#xff0c;并在项目团队内共享。在各个过程中所收集的数据经过结合相关背景的分…

MySQL中同比和环比语句如何写?

营收表如下&#xff08;表名&#xff1a;a&#xff09;如下图&#xff1a; 营收表 year month money 2021 1 1000 2021 2 1200 2022 1 1300 2022 2 1500 需要算出2022年营收同比与环比&#xff1a; 同比&#xff1a;和去年同月相比&#xff08;1300-1000/1000*100%&#xff0…

简单易用且高效的跨平台开发工具:Xojo 2023 for Mac

Xojo for Mac是Mac平台上一个跨平台的针对桌面、Web、移动和Raspberry Pi的快速应用程序开发软件。与其他多平台开发工具相比&#xff0c;Xojo for Mac为开发人员提供了显着的生产率提高。 Xojo for Mac具有拖放功能&#xff0c;使您能够快速创建用户界面设计&#xff0c;然后…

算法随笔:图论问题之割点割边

割点 定义 割点的定义&#xff1a;如果一个点被删除之后会导致整个图不再是一个连通图&#xff0c;那么这个顶点就是这个图的割点。举例&#xff1a; 上图中的点2就是一个割点&#xff0c;如果它被删除&#xff0c;则整个图被分为两个连通分量&#xff0c;不再是一个连通图。…

【交换排序】冒泡排序 与 快速排序

交换排序基本思想&#xff1a; 所谓交换&#xff0c;就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置&#xff0c;交换排序的特点是&#xff1a;将键值较大的记录向序列的尾部移动&#xff0c;键值较小的记录向序列的前部移动。 目录 1.冒泡排序 2.快…

Django笔记之数据库函数之日期函数

日期函数主要介绍两个大类&#xff0c;Extract() 和 Trunc() Extract() 函数作用是提取日期&#xff0c;比如我们可以提取一个日期字段的年份&#xff0c;月份&#xff0c;日等数据 Trunc() 的作用则是截取&#xff0c;比如 2022-06-18 12:12:12&#xff0c;我们可以根据需求…