Linux-exec函数族和system函数

参考资料:《Linux环境编程:从应用到内核》

execve函数

execve函数接口如下:

 #include <unistd.h>int execve(const char *filename, char *const argv[],char *const envp[]);

参数:

  • 第一个参数:filename是可执行的新程序的路径名,可以是绝对路径,也可以是相对于当前工作目录的相对路径;
  • 第二个参数:字符串指针组成的数组,以NULL结束。argv[0]一般对应可执行文件的文件名,也就是filename中的basename(路径名最后一个/后面的部分)。当然如果argv[0]不遵循这个约定也无妨,因为execve可以从第一个参数获取到要执行文件的路径,只要不是NULL即可。
  • 第三个参数:与C语言的main函数中的第三个参数envp一样,也是字符串指针数组,以NULL结束,指针指向的字符串的格式为name=value。

一般来说,execve()函数总是紧随fork函数之后。父进程调用fork之后,子进程执行execve函数,抛弃父进程的程序段,和父进程分道扬镳,从此天各一方,各走各路。但是也可以不执行fork,单独调用execve函数:

返回值:

execve函数返回值是特殊的,如果失败,返回-1,但如果成功,永不返回。

所以无须检查execve的返回值,只要返回,就必然是-1。可以从errno判断出出错的原因。出错的可能性非常多,手册提供了19种不同的errno,罗列了22种失败的情景。很难记住,好在大部分都不常见,常见的情况有以下几种:

  • EACCESS:这个是我们最容易想到的,就是第一个参数filename,不是个普通文件,或者该文件没有赋予可执行的权限,或者目录结构中某一级目录不可搜索,或者文件所在的文件系统是以MS_NOEXEC标志挂载的。
  • ENOENT:文件不存在。
  • ETXTBSY:存在其他进程尝试修改filename所指代的文件。
  • ENOEXEC:这个错误其实是比较高端的一种错误了,文件存在,也可以执行,但是无法执行,比如说,Windows下的可执行程序,拿到Linux下,调用execve来执行,文件的格式不对,就会返回这种错误。
// 准备外部程序 main.cpp#include <iostream>int main(int argc, char* args[])
{if (argc < 3){std::cout << "函数参数太少" << std::endl;return -1;}int a = std::stoi(args[1]);int b = std::stoi(args[2]);std::cout << "a + b = " << (a + b) << std::endl;return 0;
}
// 示例// execve函数#include <iostream>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>// 执行外部程序main
void func1()
{// 为什么使用const char*,之后又转一次?// 这是因为 "./main"、"1"、"2"在C++中都是字符串字面值,属于const char*,如果赋值给char*,就会用警告// 所以用const char*接收,之后通过const_cast去除const属性。const char* args[] = { "./main", "1", "2", nullptr };if (execve(const_cast<char*>(args[0]), const_cast<char**>(args), nullptr) == -1){perror("execve");exit(EXIT_FAILURE);}
}// 在终端执行 pwd -L 命令
void func2()
{const char* args[] = { "/bin/pwd", "-L", nullptr };if (execve(const_cast<char*>(args[0]), const_cast<char**>(args), nullptr) == -1){perror("execve");exit(EXIT_FAILURE);}
}int main()
{func1();// func2();std::cout << "never get here" << std::endl;return 0;
}

在这里插入图片描述

func1()和func2()不能同时测试,因为execve函数永不返回,无法执行完func1(),再执行func2()。

可以看到,我们在func1()里使用execve函数调用外部程序main,输出结果也是正确。

exec家族

从内核的角度来说,提供execve系统调用就足够了,但是从应用层编程的角度来讲,execve函数就并不那么好使了:

  • 第一个参数必须是绝对路径或是相对于当前工作目录的相对路径。习惯在shell下工作的用户会觉得不太方便,因为日常工作都是写ls和mkdir之类命令的,没有人会写/bin/ls或/bin/mkdir。shell提供了环境变量PATH,即可执行程序的查找路径,对于位于查找路径里的可执行程序,我们不必写出完整的路径,很方便,而execve函数享受不到这个福利,因此使用不便。
  • execve函数的第三个参数是环境变量指针数组,用户使用execve编程时不得不自己负责环境变量,书写大量的“key=value”,但大部分情况下并不需要定制环境变量,只需要使用当前的环境变量即可。

正是为了提供相应的便利,所以用户层提供了6个函数,当然,这些函数本质上都是调用execve系统调用,只是使用的方法略有不同,代码如下:

#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 execve(const char *path, char *const argv[],char *const envp[]);

上述6个函数分成上下两个半区。分类的依据是参数采用列表(l,表示list)还是数组(v,表示vector)。上半区采用列表,它们会罗列所有的参数,下半区采用数组。在每个半区之中,带p的表示可以使用环境变量PATH,带e的表示必须要自己维护环境变量,而不使用当前环境变量,

在这里插入图片描述

// 示例 返回值自行判断char* const ps_argv[] = { "ps","-ax",NULL };
char* const ps_envp[] = { "PATH=/bin:/usr/bin","TERM=console",NULL };execl("/bin/ps", "ps", "-ax", NULL);/*带p的,可以使用环境变量PATH,无须写全路径*/
execlp("ps", "ps", "-ax", NULL);/*带e的需要自己组拼环境变量*/
execle("/bin/ps", "ps", "-ax", NULL, ps_envp);execv("/bin/ps", ps_argv);/*带p的,可以使用环境变量PATH,无须写全路径*/
execvp("ps", ps_argv);/*带e的需要自己组拼环境变量*/
execve("/bin/ps", ps_argv, ps_envp);

system函数

程序可以调用system函数,来执行任意的shell命令,可以使C程序很方便地调用其他语言编写的程序。

函数接口如下:

#include <stdlib.h>int system(const char *command);

这里将需要执行的命令作为command参数,传给system函数,该函数就帮你执行该命令。

这样看来system最大的好处就在于使用方便。不需要自己来调用fork、exec和waitpid,也不需要自己处理错误,处理信号,方便省心。

但是system函数的缺点也是很明显的。首先是效率,使用system运行命令时,一般要创建两个进程,一个是shell进程,另外一个或多个是用于shell所执行的命令。如果对效率要求比较高,最好是自己直接调用fork和exec来执行既定的程序。

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

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

相关文章

合宙开发板Core_Air780E测试AT指令

一、官方资料 CORE-AIR780E 开发板是合宙通信推出的基于 Air780E 模组所开发的&#xff0c;包含电源&#xff0c;SIM 卡&#xff0c;USB&#xff0c;天线&#xff0c;音频等必要功能的最小硬件系统。以方便用户在设计前期对 Air780E 模块 进行性能评估&#xff0c;功能调试&…

更新至2021年各省经济韧性测度原始数据

更新至2021年各省经济韧性测度原始数据 1、时间&#xff1a;具体时间如下&#xff1a; 2001-2021各省一二三产业就业人数和一二三产业产值、总就业、国内生产总值数据 2002-2021年城镇登记失业人员、城镇登记失业率数据 2000-2020年各省GDP和人均GDP数据 2000-2020年各省实…

我的第一份工作经历

2024年4月6日 我是艾迪,我目前拿到了新的offer,打算入职新公司,和入职将近两年的前东家说拜拜了,在走之前,我还是想好好记录一下我的这次工作经历,方便以后好好复盘。 求职阶段 首先是求职阶段,我是以应届毕业生的身份进公司的,所以一开始并没有很好的做准备,况且当…

深入理解指针(4)

目录&#xff1a; 1.二维数组传参的本质 2.函数指针变量 3.函数指针数组 1.二维数组传参的本质 之前使用二维数组传参 #include <stdio.h> void test(int a[3][5], int r, int c) {int i 0;int j 0;for(i0; i<r; i){for(j0; j<c; j){printf("%d ", …

AJAX —— 学习(三)(完结)

目录 一、jQuery 中的 AJAX &#xff08;一&#xff09;get 方法 1.语法介绍 2.结果实现 &#xff08;二&#xff09;post 方法 1.语法介绍 2.结果实现 &#xff08;三&#xff09;通用型的 AJAX 方法 1.语法介绍 2.结果实现 二、AJAX 工具库 axios &#xff08…

环形链表 - LeetCode 热题 25

大家好&#xff01;我是曾续缘&#x1f970; 今天是《LeetCode 热题 100》系列 发车第 25 天 链表第 4 题 ❤️点赞 &#x1f44d; 收藏 ⭐再看&#xff0c;养成习惯 环形链表 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某个节点&#xff0c;可…

202112青少年软件编程(Scratch图形化)等级考试试卷(四级)

第1题&#xff1a;【 单选题】 小猫和小狗是非常好的朋友&#xff0c; 他们发明了一种加密方法&#xff1a; 用两位数字代表字母。比如 65 代表 A&#xff0c; 66 代表 B……&#xff0c; 75 代表 K&#xff0c; ……&#xff0c; 78 代表 N&#xff0c; 79 代表 O、 80 代表 …

面试经典150题——K 个一组翻转链表

1. 题目描述 2. 题目分析与解析 在这里推荐大家看一下这个解题思路&#xff1a; https://www.bilibili.com/video/BV11w411V7Ar/?spm_id_from333.337.search-card.all.click&vd_source7ea7c036902f5cb73c7f4781d1b0eaff 整体的算法思路如下&#xff1a; 初始化&#xff1a…

【第十五篇】使用BurpSuite实现IDOR越权(实战案例)

程序不存在严格的访问控制&#xff0c;从而实现未授权访问等。 如图&#xff0c;用户 ID 用于检索相关用户的数据&#xff0c;以呈现帐户页面。 思路&#xff1a;进行爆破或修改请求后发包&#xff0c;查看是否存在IDOR越权 操作&#xff1a;遍历ID参数&#xff0c;查看回显 …

JWT/JWS/JWE

JWT(JSON Web Token)&#xff1a;一种基于JSON格式&#xff0c;用于在Web应用中安全传递用户身份验证和授权信息的标准令牌&#xff0c;可以包含签名(JWS)和加密(JWE)的信息 MacAlgorithm(Message Authentication Code Algorithm)&#xff1a;消息认证码算法 HMAC(Hash-based…

Vue - 3( 15000 字 Vue 入门级教程)

一&#xff1a;初识 Vue 1.1 收集表单数据 收集表单数据在Vue.js中是一个常见且重要的任务&#xff0c;它使得前端交互变得更加灵活和直观。 Vue中&#xff0c;我们通常使用v-model指令来实现表单元素与数据之间的双向绑定&#xff0c;从而实现数据的收集和更新。下面总结了…

内容检索(2024.04.07)

随着创作数量的增加&#xff0c;博客文章所涉及的内容越来越庞杂&#xff0c;为了更为方便地阅读&#xff0c;后续更新发布的文章将陆续在此汇总并附上原文链接&#xff0c;感兴趣的小伙伴们可持续关注文章发布动态&#xff01; 本期更新内容&#xff1a; 1. 真实案例分享--P…