execve系统调用_Linux系统编程——进程替换:exec 函数族

在 Windows 平台下,我们可以通过双击运行可执行程序,让这个可执行程序成为一个进程;而在 Linux 平台,我们可以通过 ./ 运行,让一个可执行程序成为一个进程。

但是,如果我们本来就运行着一个程序(进程),我们如何在这个进程内部启动一个外部程序,由内核将这个外部程序读入内存,使其执行起来成为一个进程呢?这里我们通过 exec 函数族实现。

exec 函数族,顾名思义,就是一簇函数,在 Linux 中,并不存在 exec() 函数,exec 指的是一组函数,一共有 6 个:

#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[]);

其中只有execve()是真正意义上的系统调用,其它都是在此基础上经过包装的库函数。

exec 函数族提供了六种在进程中启动另一个程序的方法。exec 函数族的作用是根据指定的文件名或目录名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进程内部执行一个可执行文件。

进程调用一种 exec 函数时,该进程完全由新程序替换,而新程序则从其 main 函数开始执行。因为调用 exec 并不创建新进程,所以前后的进程 ID (当然还有父进程号、进程组号、当前工作目录……)并未改变。exec 只是用另一个新程序替换了当前进程的正文、数据、堆和栈段(进程替换)。

6271ba933d56b0e0ac5d64d2a2462f5c.png

exec 函数族的 6 个函数看起来似乎很复杂,但实际上无论是作用还是用法都非常相似,只有很微小的差别。

83254300ce928bfa209978e3ccc13461.png

l(list):参数地址列表,以空指针结尾。

v(vector):存有各参数地址的指针数组的地址。

p(path):按 PATH 环境变量指定的目录搜索可执行文件。

e(environment):存有环境变量字符串地址的指针数组的地址。

exec 函数族装入并运行可执行程序 path/file,并将参数 arg0 ( arg1, arg2, argv[], envp[] ) 传递给此程序。

exec 函数族与一般的函数不同,exec 函数族中的函数执行成功后不会返回,而且,exec 函数族下面的代码执行不到。只有调用失败了,它们才会返回 -1,失败后从原程序的调用点接着往下执行。

需要C/C++ Linux服务器架构师学习资料加qun获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享

2569e45fe2a5e79ed12d62f08201c657.png

execl() 示例代码:

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{printf("before execnn");/* /bin/ls:外部程序,这里是/bin目录的 ls 可执行程序,必须带上路径(相对或绝对)ls:没有意义,如果需要给这个外部程序传参,这里必须要写上字符串,至于字符串内容任意-a,-l,-h:给外部程序 ls 传的参数NULL:这个必须写上,代表给外部程序 ls 传参结束*/execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);// 如果 execl() 执行成功,下面执行不到,因为当前进程已经被执行的 ls 替换了perror("execl");printf("after execnn");return 0;
}

运行结果如下:

e386ebddcb88a145edb3a3f5173a178a.png

execv()示例代码:

execv() 和 execl() 的用法基本是一样的,无非将列表传参,改为用指针数组。

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{// execv() 和 execl() 的用法基本是一样的,无非将列表传参,改为用指针数组// execl("/bin/ls", "ls", "-a", "-l", "-h", NULL);/* 指针数组ls:没有意义,如果需要给这个外部程序传参,这里必须要写上字符串,至于字符串内容任意-a,-l,-h:给外部程序 ls 传的参数NULL:这个必须写上,代表给外部程序 ls 传参结束*/char *arg[]={"ls", "-a", "-l", "-h", NULL};// /bin/ls:外部程序,这里是/bin目录的 ls 可执行程序,必须带上路径(相对或绝对)// arg: 上面定义的指针数组地址execv("/bin/ls", arg);perror("execv");return 0;
}

execlp() 或 execvp() 示例代码:

execlp() 和 execl() 的区别在于,execlp() 指定的可执行程序可以不带路径名,如果不带路径名的话,会在环境变量 PATH指定的目录里寻找这个可执行程序,而 execl() 指定的可执行程序,必须带上路径名。

#include <stdio.h>
#include <unistd.h>int main(int argc, char *argv[])
{// 第一个参数 "ls",没有带路径名,在环境变量 PATH 里寻找这个可执行程序// 其它参数用法和 execl() 一样execlp("ls", "ls", "-a", "-l", "-h", NULL);/*char *arg[]={"ls", "-a", "-l", "-h", NULL};execvp("ls", arg);*/perror("execlp");return 0;
}

execle() 或 execve() 示例代码:

execle() 和 execve() 改变的是 exec 启动的程序的环境变量(只会改变进程的环境变量,不会影响系统的环境变量),其他四个函数启动的程序则使用默认系统环境变量。

execle()示例代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h> // getenv()int main(int argc, char *argv[])
{// getenv() 获取指定环境变量的值printf("before exec:USER=%s, HOME=%sn", getenv("USER"), getenv("HOME"));// 指针数据char *env[]={"USER=MIKE", "HOME=/tmp", NULL};/* ./mike:外部程序,当前路径的 mike 程序,通过 gcc mike.c -o mike 编译mike:这里没有意义NULL:给 mike 程序传参结束env:改变 mike 程序的环境变量,正确来说,让 mike 程序只保留 env 的环境变量*/execle("./mike", "mike", NULL, env);/*char *arg[]={"mike", NULL};		execve("./mike", arg, env);	*/perror("execle");return 0;
}

外部程序,mike.c 示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>int main(int argc, char *argv[])
{printf("nin the mike fun, after exec: n");printf("USER=%sn", getenv("USER"));printf("HOME=%sn", getenv("HOME"));return 0;
}

运行结果如下:

38d6c51df7cfca68cfc4f090957fd236.png

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

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

相关文章

数据结构之链表--单链表

Hello&#xff0c;大家好&#xff01;好久不见了&#xff0c;之前一直在忙于一些琐事&#xff0c;最近半个月内会将数据结构的各种数据结构实现出来&#xff0c;一个挺有意思的东西。 这次我将要介绍的是链表。链表有单链表&#xff0c;单向循环链表&#xff0c;双向链表&…

idea shell 使用linux_Linux使用shell定时任务实现ffmpeg视频转码和截图

Linux安装操作系统&#xff1a;CentOS7 ffmpeg版本&#xff1a;3.4.1安装先访问ffmpeg官网下载linux安装包 http://ffmpeg.org/download.html &#xff0c;这里我下载的是官方已经编译过的版本&#xff0c;别问我为啥不自己编译&#xff0c;因为我自己编译耗费了好久&#xff0…

链表之单循环链表

单链表之单循环链表 单向循环链表的关键所在是最后一个节点的next存储了头节点的地址&#xff0c;这是对单向循环链表的操作关键所在 接下来我将实现增、删、改、查这四项最基本的操作&#xff0c;剩下你想要什么操作自己可以根据对链表的理解添加对应的数据操作 后面main函数…

曾辉机器人_武昌理工学子在2020年中国机器人大赛中夺冠

“它在过弯的时候非常稳&#xff0c;而且速度快&#xff0c;跑完一圈的时间比第二名少十秒左右。”武昌理工学院学生余辉激动地说。11月27日从武昌理工学院获悉&#xff0c;在刚刚结束的2020中国机器人大赛中&#xff0c;武昌理工学院人工智能学院“晨旭队”&#xff0c;经过激…

链表之双向链表

又是敲代码学习的一天&#xff0c;虽然学的很痛苦&#xff0c;但是看到自己学完后有成果出来还是 很高兴的。 接下来废话不多说直接上代码&#xff0c;代码里有各个函数的解释说明&#xff0c;贯穿着我对这个双向链表的理解 //感觉这个双向链表&#xff0c;就是在单向链表中稍…

react手机机端css_react工程搭建系列之---移动端适配与antd-mobile高清适配方案

一、逻辑像素(css像素)与物理像素(设备像素)机型逻辑像素物理像素Scale Factoriphone 3GS320 x 480320 x 4801xiphone 4320 x 480640 x 9602xiphone 4S320 x 480640 x 9602xiphone 5320 x 568640 x 11362xiphone 5C320 x 568640 x 11362xiphone 5S320 x 568640 x 11362xiphone …

升级bios_华硕400系主板升级BIOS:静待11代酷睿CPU

1月份对PC玩家来说还有很多惊喜&#xff0c;AMD、NVIDIA、Intel都会在CES上推出新一代产品&#xff0c;其中Intel针对桌面端的产品是11代酷睿&#xff0c;代号Rocket Lake-S。Rocket Lake仍将采用14nm制造工艺&#xff0c;基本确定也将是Intel最后一代14nm处理器。CPU架构方面&…

win10共享打印错误0x0000006_Win10连接共享打印机提示0x80070035错误的解决办法

关于Win10连接共享打印机提示0x80070035错误&#xff0c;概括起来主要有以下几个方面。下面直接上解决方法&#xff0c;请碰到这个错误的朋友自己按照下面的方法一一排查。因为主要就是每个人安装的系统不一样&#xff0c;现在系统封装工具太多了&#xff0c;流程也傻瓜化了&am…

用vscode编写静态页面_开发中实用的VSCode插件推荐

本篇文章给大家介绍一下开发中实用的VSCode插件推荐。有一定的参考价值&#xff0c;有需要的朋友可以参考一下&#xff0c;希望对大家有所帮助。工欲善其事必先利其器&#xff0c;以下是本人为前端开发收集的vscode插件&#xff0c;有需要的话赶紧mark起来吧~一、代码片段类插件…

取得数组下标_《零基础C++入门教程》——(8)搞定二维数组与循环嵌套

一、学习目标了解二维数组的使用方法了解循环嵌套的使用方法目录预备第一篇&#xff0c;使用软件介绍在这一篇&#xff0c;C与C使用的软件是一样的&#xff0c;查看这篇即可&#xff1a;《零基础看得懂的C语言入门教程》——(二)简单带你了解流程 想了解编译原理和学习方法点这…

缺陷调研报告_工厂的缺陷的分析报告及产生原因

精彩文档锻造成形过程中的缺陷及其防止方法一、钢锭的缺陷钢锭有下列主要的缺陷&#xff1a;(1)缩孔和疏松钢锭中缩孔和疏松是不可避免的缺陷&#xff0c;但它们出现的部位可以控制。钢锭中顶端的保温冒口&#xff0c;造成钢液缓慢冷却和最后凝固的条件&#xff0c;一方面使锭身…

linux 的swap具体分析_Linux SWAP 深度解读

概述本文讨论的 swap基于Linux4.4内核代码 。Linux内存管理是一套非常复杂的系统&#xff0c;而swap只是其中一个很小的处理逻辑。希望本文能让读者了解Linux对swap的使用大概是什么样子。阅读完本文&#xff0c;应该可以帮你解决以下问题&#xff1a;1、 swap到底是干嘛的&…

物联卡的使用_物联卡在手机上使用有什么影响?网友:寿命分别是3个月,16天,9天...

个人使用物联卡是否合法&#xff1f;当然&#xff0c;个人是可以使用的&#xff0c;只不过是使用在除手机、平板以外的智能设备上。重点提醒&#xff1a;手机和平板除外。物联卡&#xff0c;是运营商为物流网服务企业提供的用于智能终端设备联网的&#xff0c;仅面对企业用户进…

多行文字cad提取数据_利用CAD自带的数据提取功能手动提取假表格至Excel

“吾生也有涯&#xff0c;而知也无涯&#xff0c;以有涯随无涯&#xff0c;殆已&#xff01;”&#xff0c;在已经有了免费的“源泉设计”插件可以自动提取假表格至Excel之后&#xff0c;笔者为什么还要讲解手动提取的方法&#xff1f;无他&#xff0c;生命在于折(zhuang)腾(bi…

gridview标题居中显示_Pr:制作片尾滚动字幕(旧版标题法)

本文介绍使用 Pr 的旧版标题设计器来制作传统片尾滚动字幕的方法。效果视频◆ ◆ ◆一般方法与步骤1、首先&#xff0c;将文字内容输入到一个文本文件中。按 Ctrl/Cmd A 全选&#xff0c;按 Ctrl/Cmd C 复制以备用。2、Pr菜单&#xff1a;文件/新建/旧版标题。3、点击“滚动…

mysql临时表空间_MySQL 5.7 深度解析: 临时表空间

先来说说临时表的概念。 临时表顾名思义&#xff0c;就是临时的&#xff0c;用完销毁掉的表。 数据既可以保存在临时的文件系统上&#xff0c;也可以保存在固定的磁盘文件系统上。 临时表有下面几种&#xff1a;全局临时表这种临时表从数据库实例启动后开始生效&#xff0c;在数…

mysql 从库状态_大神教你自动发现监控mysql从库状态

导读zabbix从库如果复制有问题&#xff0c;在主库机器有问题的时候&#xff0c;切为主就会导致数据的丢失。或者主从分离的时候&#xff0c;如果从库出现延时状态的话&#xff0c;会导致前端页面展示的数据不是为最新的数据。因此&#xff0c;监控mysql从库的状态是必要的。mys…

mysql查看session对应的ip_Mysql 查看session连接数,状态 | 学步园

命令&#xff1a; showprocesslist; 如果是root帐号&#xff0c;你能看到所有用户的当前连接。如果是其它普通帐号&#xff0c;只能看到自己占用的连接。 showprocesslist;只列出前100条&#xff0c;如果想全列出请使用showfull processlist; mysql> show processlist;命令&…

mysql集群fuzhi_MySQL集群 和MySQL主从复制的不同

主从复制理论上支持无穷大的从库个数&#xff0c;实际情况下&#xff0c;受服务器带宽和读写能力的影响请参考mysql官方手册的建议&#xff1a;理论上&#xff0c;通过使用单个主服务器/多从服务器设置&#xff0c;可以通过添加更多的从服务器来扩充系统&#xff0c;直到用完网…

mysql 查询一个字段快还是一条记录快_mysql (优化)查询一条再筛选某个字段和直接查询该条的某个字段的效率比较...

查询所有&#xff0c;10000次&#xff0c;$sql "select * from mh_user where (username‘333‘) and (password‘xxx‘)";总共耗时1.1420359611511查询username字段&#xff0c;10000次。$sql "select username from mh_user where (username‘333‘) and (p…