当前位置: 首页 > news >正文

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)》

相关文章:

  • 个人获取Wiley 、ScienceDirect、SpringerLink三个数据库文献的方法
  • 支持分页的环形队列
  • 海云安董事长谢朝海博士出席2024年中国国际服务贸易交易会“大模型应用创新论坛”
  • Golang | Leetcode Golang题解之第442题数组中重复的数据
  • Golang | Leetcode Golang题解之第436题寻找右区间
  • 【Golang】关于Go语言字符串转换strconv
  • vue3实现打字机的效果,可以换行
  • 3.整数二分
  • YOLOv9改进策略【注意力机制篇】| 蒙特卡罗注意力(MCAttn)模块,提高小目标的关注度
  • 无人机在农业方面的应用!
  • java通过redis完成幂等性操作
  • 基于RPA+BERT的文档辅助“悦读”系统 | OPENAIGC开发者大赛高校组AI创作力奖
  • 前端学习笔记-JS进阶篇-02
  • 54 循环神经网络RNN_by《李沐:动手学深度学习v2》pytorch版
  • 安卓Android压力测试与性能测试详解!
  • 【挥舞JS】JS实现继承,封装一个extends方法
  • 2019年如何成为全栈工程师?
  • Git的一些常用操作
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • Java,console输出实时的转向GUI textbox
  • Java基本数据类型之Number
  • js继承的实现方法
  • Material Design
  • Twitter赢在开放,三年创造奇迹
  • 阿里云ubuntu14.04 Nginx反向代理Nodejs
  • 番外篇1:在Windows环境下安装JDK
  • 服务器之间,相同帐号,实现免密钥登录
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 工作中总结前端开发流程--vue项目
  • 设计模式(12)迭代器模式(讲解+应用)
  • 使用 Xcode 的 Target 区分开发和生产环境
  • 使用API自动生成工具优化前端工作流
  • 算法-图和图算法
  • 延迟脚本的方式
  • C# - 为值类型重定义相等性
  • FaaS 的简单实践
  • JavaScript 新语法详解:Class 的私有属性与私有方法 ...
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • $(function(){})与(function($){....})(jQuery)的区别
  • (4)(4.6) Triducer
  • (阿里云在线播放)基于SpringBoot+Vue前后端分离的在线教育平台项目
  • (第二周)效能测试
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot工单管理系统 毕业设计 964158
  • (七)c52学习之旅-中断
  • (学习日记)2024.02.29:UCOSIII第二节
  • (原創) 如何使用ISO C++讀寫BMP圖檔? (C/C++) (Image Processing)
  • (转)Android中使用ormlite实现持久化(一)--HelloOrmLite
  • **CentOS7安装Maven**
  • .CSS-hover 的解释
  • .net 7和core版 SignalR
  • .net dataexcel 脚本公式 函数源码
  • .NET Framework杂记
  • .NET 命令行参数包含应用程序路径吗?