unix中的exec族函数介绍

一、前言

本文将介绍unix中exec族函数,包括其作用以及使用方法。当一个进程调用fork函数创建一个新进程后,新进程可以直接执行原本正文段的其他内容,但更多时候,我们在一个进程中调用fork创建新的进程后,希望新进程能够执行其他的程序。(举个实际的例子,A进程调用fork后,我们更多的时候是希望子进程能够运行B程序,而不是用于处理A进程特定的内容)exec族函数的作用就是让一个进程执行另一个程序。
本文将围绕如下内容展开:
1.exec族函数的原理
2.exec族各函数介绍

二、exec族函数原理

当一个进程调用了exec类函数后,该进程的正文段、数据段、堆、栈都替换为磁盘中其他指定的程序的内容,即子进程的进程空间被替换了其他内容。不过子进程的PID是不变的。子进程从新程序的main函数开始执行。新程序会继承子进程的如下信息:

  1. 文件描述符:新程序会继承调用进程的打开文件描述符,包括标准输入、标准输出和标准错误,除非这些文件描述符在调用 exec 前被显式地关闭或更改。
  2. 环境变量:新程序会继承调用进程的环境变量。
  3. 当前工作目录:新程序会继承调用进程的当前工作目录。
  4. 进程用户和组 ID:新程序会继承调用进程的用户 ID(UID)和组 ID(GID)。
  5. 信号处理状态:新程序会继承调用进程的信号处理状态,包括信号屏蔽字。
  6. 一些状态信息:比如进程优先级(nice值)等。

三、exec类函数介绍

unix提供了7个exec类函数,本小节将分别介绍这7种函数。

3.1 execl

头文件:#include <unistd.h>
函数原型:int execl(const char *path, const char
*arg0, …, (char *) NULL);
传入参数:
{
path:要执行的程序的路径。
arg0:新程序的第一个参数,通常是程序的名称(用于 argv[0])。
…:紧接着的参数列表,用于传递给新程序的其他参数,最后需要以NULL 结束。
}
返回值: 成功时,execl 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。

参考代码:

/*************************************************************************> File Name: exec_test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时12分08秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>/************************************************************************                              MACRO**********************************************************************//************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;pid_t pid;if((pid = fork()) < 0){printf("fork fail!\n");}else if(pid == 0){if(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1){printf("execl fail!\n");}}else{printf("This is father process! child's pid = %d\n",pid);}return ret;
}

需要调用的程序代码如下:

/*************************************************************************> File Name: test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时16分00秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>/************************************************************************                              MACRO**********************************************************************//************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;while(1){printf("This is %s!\n",__FILE__);sleep(1);}return ret;
}

运行结果如下所示:
在这里插入图片描述

(3.1-1)

3.2 execv

头文件:#include <unistd.h>
函数原型:int execv(const char *path, char *const
argv[]);
传入参数:
{
path:要执行的程序的路径。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于 argv[0]),最后一个元素必须是 NULL以标示参数列表的结束。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。

参考代码如下:

/*************************************************************************> File Name: exec_test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时12分08秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>/************************************************************************                              MACRO**********************************************************************/
#define EXECV/************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;pid_t pid;
#ifdef EXECVchar *arg[] = {NULL};
#endifif((pid = fork()) < 0){printf("fork fail!\n");}else if(pid == 0){
#ifdef EXECLif(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1){printf("execl fail!\n");}
#elif defined(EXECV)if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1){printf("execl fail!\n");}
#endif}else{printf("This is father process! child's pid = %d\n",pid);}return ret;
}

运行结果如下图所示:
在这里插入图片描述

(3.2-1)

3.3 execle

头文件:#include <unistd.h>
函数原型:int execle(const char *path, const char
*arg0, …, (char *) NULL, char *const envp[]);
传入参数:
{
path:要执行的程序的路径。
arg0:新程序的第一个参数,通常是程序的名称(用于 argv[0])。
…:紧接着的参数列表,用于传递给新程序的其他参数,最后需要以 NULL 结束。
envp: 一个指向环境变量字符串数组的指针,环境变量以
NULL 结尾。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。 这个函数与上面两个的区别就是能够设置环境变量。

参考代码如下:

/*************************************************************************> File Name: exec_test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时12分08秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>/************************************************************************                              MACRO**********************************************************************/
//#define EXECV
#define EXECLE/************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;pid_t pid;
#ifdef EXECVchar *arg[] = {NULL};
#endif#ifdef EXECLEchar *envp[] = {"AUTHER=Conbiao",NULL};
#endifif((pid = fork()) < 0){printf("fork fail!\n");}else if(pid == 0){
#ifdef EXECLif(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1){printf("execl fail!\n");}
#elif defined(EXECV)if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1){printf("execl fail!\n");}
#elif defined(EXECLE)if(execle("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test",NULL,envp) == -1){printf("execl fail!\n");}
#endif}else{printf("This is father process! child's pid = %d\n",pid);}return ret;
}

test.c添加获取环境变量的操作,代码如下:

/*************************************************************************> File Name: test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时16分00秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>/************************************************************************                              MACRO**********************************************************************//************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;printf("<%s> Author is: %s\n",__FILE__,getenv("AUTHER"));while(1){printf("This is %s!\n",__FILE__);sleep(1);}return ret;
}

运行结果如下所示:
在这里插入图片描述

(3.3-1)

3.4 execve

头文件:#include <unistd.h>
函数原型:int execve(const char *path, char *const
argv[], char *const envp[]);
传入参数:
{
path:要执行的程序的路径。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于 argv[0]),最后一个元素必须是 NULL以标示参数列表的结束。
envp: 一个指向环境变量字符串数组的指针,环境变量以 NULL 结尾。
}
返回值: 成功时,execv不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno 设定相应的错误代码。

这个函数其实就是将一个个参数以字符串数组的形式传入而已,在此就不做过多的介绍了。

3.5 execlp

头文件:#include <unistd.h>
函数原型:int execlp(const char *file, const char
*arg0, …, (char *) NULL);
传入参数:
{
file:要执行的程序的名称。该名称可以是相对路径或可执行文件的名称,execlp 函数会在环境变量 PATH 指定的目录中搜索该程序。
arg0:新程序的第一个参数,通常是程序的名称(用于 argv[0])。 …: 后续参数,用于传递给新程序的其他参数,最后需要以NULL 结束。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno设定相应的错误代码。

参考代码如下:

/*************************************************************************> File Name: exec_test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时12分08秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>/************************************************************************                              MACRO**********************************************************************/
//#define EXECV
//#define EXECLE
#define EXECLP
/************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;pid_t pid;
#ifdef EXECVchar *arg[] = {NULL};
#endif#ifdef EXECLEchar *envp[] = {"AUTHER=Conbiao",NULL};
#endifif((pid = fork()) < 0){printf("fork fail!\n");}else if(pid == 0){
#ifdef EXECLif(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1){printf("execl fail!\n");}
#elif defined(EXECV)if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1){printf("execl fail!\n");}
#elif defined(EXECLE)if(execle("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test",NULL,envp) == -1){printf("execl fail!\n");}
#elif defined(EXECLP)if(execlp("ls","-l",NULL) == -1){printf("execl fail!\n");}
#endif}else{printf("This is father process! child's pid = %d\n",pid);}return ret;
}

运行结果如下:
在这里插入图片描述

(3.5-1)

3.6 execvp

头文件:#include <unistd.h>
函数原型:int execvp(const char *file, char *const
argv[]);
传入参数:
{
file:要执行的程序的名称。该名称可以是相对路径或仅是可执行文件的名称,execvp 会在环境变量PATH 指定的目录中搜索该程序。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于argv[0]),最后一个元素必须是 NULL 以标示参数列表的结束。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。出错时,返回 -1,并通过 errno 设定相应的错误代码。

该函数的功能与execv类似,就不做过多的介绍了。

3.7 fexecve

头文件:#include <unistd.h>
函数原型:int fexecve(int fd, char *const argv[],
char *const envp[]);
传入参数: { fd:一个文件描述符,指向要执行的可执行文件。这个文件描述符必须是通过 open系统调用以读执行模式打开的。
argv:参数数组,包含新程序的参数列表。数组的第一个元素通常是程序名称(用于argv[0]),最后一个元素必须是 NULL 以标示参数列表的结束。
envp: 一个指向环境变量字符串数组的指针,环境变量以 NULL结尾。
}
返回值: 成功时,execv 不会返回,如果返回,通常表示出错。 出错时,返回 -1,并通过 errno 设定相应的错误代码。

参考代码如下:

/*************************************************************************> File Name: exec_test.c> Author: conbiao> Created Time: 2024年09月29日 星期日 15时12分08秒************************************************************************//************************************************************************                             HEADER**********************************************************************/
#include<stdio.h>
#include<unistd.h>
#include<sys/wait.h>
#include<fcntl.h>
/************************************************************************                              MACRO**********************************************************************/
//#define EXECV
//#define EXECLE
//#define EXECLP
#define FEXECVE
/************************************************************************                          GLOBAL VARIABLE**********************************************************************//************************************************************************                       FUNCTION DESCRIPTION**********************************************************************//***********************************************************************
* FUNCTION NAME:***********************************************************************
*
* Summary:
*
* Params:
*
* Return:
*
***********************************************************************//************************************************************************                                MAIN**********************************************************************/
int main(int argc, char *argv[])
{int ret = 0;pid_t pid;
#ifdef FEXECVEchar *arg[] = {NULL};
#endif#ifdef FEXECVEchar *envp[] = {"AUTHER=Conbiao",NULL};
#endifif((pid = fork()) < 0){printf("fork fail!\n");}else if(pid == 0){
#ifdef EXECLif(execl("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test", NULL) == -1){printf("execl fail!\n");}
#elif defined(EXECV)if(execv("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", arg) == -1){printf("execl fail!\n");}
#elif defined(EXECLE)if(execle("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test", "test",NULL,envp) == -1){printf("execl fail!\n");}
#elif defined(EXECLP)if(execlp("ls","-l",NULL) == -1){printf("execl fail!\n");}
#elif defined(FEXECVE)int fd = open("/home/bb-yy/zijide/study/system/linux/unix-like-app/exec/test",O_EXCL | O_RDONLY);if(fd == -1){printf("open file fail!\n");}else{if(fexecve(fd,arg,envp) == -1){printf("fexecve fail!\n");}}
#endif}else{printf("This is father process! child's pid = %d\n",pid);}return ret;
}

运行结果如下:
在这里插入图片描述

(3.7-1)

参考资料:

《UNIX环境高级编程(第3版) (史蒂文斯 (W.Richard Stevens) 拉戈 (Stephen A.Rago))
(Z-Library)》

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

ApiSix 插件开发

版本 3.0.1 创建插件目录和文件 cd ./example/ mkdir -p apisix/plugins cd apisix/plugins touch my_plugin.lua结构如下&#xff1a; 编写脚本 local core require("apisix.core")local plugin_name "my_plugin"local schema {type "obje…

MySQL约束:外键约束

下面先创建两张表用来作为实验样例 1.创建dept表 create table dept(id int auto_increment comment ID primary key,name varchar(50) not null comment 部门名称 ) comment 部门表;INSERT INTO dept (id, name) VALUES (1, 研发部), (2, 市场部), (3, 财务部), (4, 销售部…

基于服务网格的集群访问控制

随着容器化、云原生等概念的火热&#xff0c;越来越多的应用都开始选择支持云原生部署&#xff0c;但是对于大型企业应用来说&#xff0c;各种为服务的拆分会导致集群运维的压力越来越大&#xff0c;尤其是服务之间的安全通信至关重要。 在容器化集群中&#xff0c;传统的基于…

同元软控参展2024超临界二氧化碳动力循环与多能互补系统国际会议

9月20-23日&#xff0c;2024超临界二氧化碳动力循环与多能互补系统国际会议&#xff08;简称ICSPC2024&#xff09;在上海召开。会议由中国科学院工程热物理研究所、中国工程热物理学会主办&#xff0c;华北电力大学、西安热工研究院有限公司为联合主办单位。同元软控携核反应堆…

7.3树形查找

7.3.1二叉排序树 1.定义 目的:提供查找删除,插入关键字的速度 二叉排序树的特性: 左子树<根节点<右子树左右字数也分别是一棵二叉树 对二叉排序树进行中序遍历,可以得到一个递增的有序序列 2.二叉排序树的查找 查找从根节点开始,沿分支逐层向下比较的过程 二叉排序…

foxmail登录不了hotmail的解决办法

foxmail登录不了hotmail 由于hotmail的信息安全保护&#xff0c;9.16号就在foxmail登录不了&#xff0c;因为习惯了foxmail&#xff0c;且微软改了验证方式&#xff0c;换要他们的客户端才行&#xff0c;就感觉好麻烦。 在foxmail输入原密码报错 修改验证方式 也是会报错 解决…

第十三届蓝桥杯真题Java c组C.纸张尺寸(持续更新)

博客主页&#xff1a;音符犹如代码系列专栏&#xff1a;蓝桥杯关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 【问题描述】 在 ISO 国际标准中定义了 A0 纸张的大小为 1189mm 841mm&#…

LLM推理需要多大GPU?背完再去面试

在实际工作中&#xff0c;经常有人问&#xff0c;7B、14B 或 70B 的模型需要多大的显存才能推理&#xff1f;如果微调他们又需要多大的显存呢&#xff1f; 为了回答这个问题整理一份训练或推理需要显存的计算方式。如果大家对具体细节不感兴趣&#xff0c;可以直接参考经验法则…

original多因子图绘制

成品参考 首先导入数据 设置过程 设置X轴 设置图 双击空白部分设置图层宽度&#xff08;也需要设置高度&#xff09; 颜色配置 1.删除边框 合适的参数与颜色&#xff08;设置为单色&#xff09;

【Python】Python多行输入储存为字典,值为列表

1.储存在变量中 # 输入格式&#xff1a;3 5 tabel, customer map(int, input().split()) print("table:", tabel) print("customer:", customer) 2.储存在列表中 #输入格式&#xff1a;2 4 2 tabel_number [int(x) for x in input().split()] print(&q…

跨国企业如何布局知识产权战略以应对国际条约的挑战与机遇?

在跨国企业的全球运营中&#xff0c;知识产权的战略布局显得尤为重要。面对复杂多变的国际环境&#xff0c;跨国企业如何在全球范围内有效保护其知识产权&#xff0c;同时利用国际条约促进合作并应对挑战&#xff0c;成为了一个亟待探讨的问题。 跨国企业知识产权的全球布局 1…

项目管理系统中的风险管理:如何识别和应对项目风险?

在现代项目管理中&#xff0c;风险管理是确保项目成功的关键因素之一。无论是技术、资源还是市场的变化&#xff0c;风险无处不在。有效的风险管理能够帮助团队识别潜在问题并制定应对策略&#xff0c;从而避免项目延误和预算超支。项目管理系统在这一过程中扮演着重要角色&…

微积分入门(真的很入门)

前置知识 前置知识&#xff1a;极限 我们要求 lim ⁡ x → 1 x 2 − 1 x − 1 \lim\limits_{x \to 1}\dfrac{x^2-1}{x-1} x→1lim​x−1x2−1​。 右边我们都知道是什么意思&#xff0c;那左边是什么呢&#xff1f; 意思就是&#xff0c;当 x x x 无限接近 1 1 1 时&…

相亲交友系统的社会影响:家庭结构的变化

随着互联网技术的发展&#xff0c;相亲交友系统已成为许多单身人士寻找伴侣的重要途径。这些平台不仅改变了人们的社交方式&#xff0c;还对家庭结构产生了深远的影响。本文将探讨相亲交友系统如何促使家庭结构发生变化&#xff0c;开发h17711347205并通过简单的Python代码示例…

华为OD机试 - 对称美学(Python/JS/C/C++ 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

kubernetes基础配置(入门操作)

资源管理 一、资源管理方式 1.命令式对象管理&#xff1a;直接使用命令去操作kubernetes资源 [rootmaster ~]# kubectl run nginx-pod --imagenginx --port80 kubectl run --generatordeployment/apps.v1 is DEPRECATED and will be removed in a future version. Use kubect…

煤矿厂智能化可视化:提升安全与效率

运用图扑可视化技术对煤矿厂进行实时监控与数据分析&#xff0c;提高安全管理水平和生产效率。

Java8/9/10/11新特性

目录 一、 Lambda表达式二、函数式(Functional)接口三、方法引用与构造器引用3.1、方法引用3.2 构造器引用和数组引用3.2.1 构造器引用3.2.2 数组引用 四、 强大的Stream API4.1 Stream API说明4.2 Stream 的操作三个步骤4.3 创建 Stream方式4.4 、Stream 的中间操作4.4.1 筛选…

VMware Tools安装——VMware Tools是灰色的,不能安装, (不带图形化界面的虚拟机,只有命令行的模式!!!)

问题 VMware Workstation 中“ 安装VMware Tools”是灰色的&#xff0c;无法点击安装 解决 1.挂载镜像文件 打开 VMware&#xff0c;点击虚拟机设置>>CD/DVD&#xff0c;选择“使用ISO映像文件”&#xff0c;点击“浏览” 再选择 VMware 安装目录中的 linux.iso 文件&a…

FPGA到底要怎么学?一篇文章直接让你搞清楚!!!

学好FPGA&#xff08;现场可编程门阵列&#xff09;涉及理论学习和实践操作的结合。以下是学习FPGA的基本流程和建议&#xff1a; 关注我&#xff0c;我会更新更多的知识&#xff0c;这会给你很多的帮助。 1. 理论基础 数字逻辑&#xff1a;了解基本的逻辑门、组合逻辑、时序…