[Linux]exec系列函数

news/2025/2/25 13:08:45/文章来源:https://www.cnblogs.com/wzhiheng/p/18565491

exec系列函数

exec系列函数是用来进行程序的替换的。

替换原理

当使用fork函数创建子进程后,子进程会执行与父进程相同的代码(但也有可能执行不同的代码分支),子进程会通过调用exec函数来执行另一个程序。当调用exec函数时,会用新程序的代码和数据来覆盖当前进程的代码和数据(也就是写时拷贝,可以看看这一篇博客[Linux]进程地址空间 - 羡鱼OvO - 博客园)。由于调用exec函数并不是创建新的进程,所以调用前后该进程的pid并不会发生改变,这样从操作系统的角度看,仍然是同一个进程在运行,只是其执行的代码和数据发生了根本性的变化。

exec系列函数返回值问题

exec系列函数如果执行成功,则不会返回;如果执行失败,则会返回-1。失败返回-1好理解,但是为什么执行成功的话没有返回值呢?

那是因为,当在调用exec系列函数之后,原本的代码和数据都会被新程序的代码和数据所覆盖。也就是说,当执行完exec系列函数后,exec函数后的代码都不会被执行,所以它要返回值也没有用。

exec系列函数

  1. execl()

    • 函数原型:int execl(const char *path, const char *arg, ...)

    • 功能:通过指定程序的路径path和一系列以空指针结尾的命令行参数来执行新程序。

    • 示例:execl("/usr/bin/ls", "ls", "-l", "-a", NULL);执行ls -la命令。

      #include <stdio.h>
      #include <unistd.h>
      #include <assert.h>int main()
      {printf("process is running...\n");execl("/usr/bin/ls", "ls", "--color=auto", "-a", "-l", NULL);printf("process running done......\n");//程序被替换,不执行该语句return 0;
      }
      

      如上,就实现了运行我们自己的程序,来执行其他程序的方法。

      当然,也可以使用子进程的方式来执行程序替换。

      #include <stdio.h>
      #include <unistd.h>
      #include <assert.h>
      #include <sys/wait.h>
      #include <sys/types.h>
      #include <stdlib.h>
      int main()
      {printf("process is running...\n");pid_t id = fork();assert(id != -1);if (id == 0){//子进程execl("/usr/bin/ls", "ls", "--color=auto", "-a", "-l", NULL);exit(1);}//父进程int status = 0;pid_t ret = waitpid(id, &status, 0);//等待子进程if (ret > 0) printf("wait success: sig: %d, exit code: %d\n", WEXITSTATUS(status), WIFEXITED(status) );printf("process running done......\n");return 0;
      }
  2. execlp()

    • 函数原型:int execlp(const char *file, const char *arg, ...)

    • 功能:会在环境变量PATH中自动搜索指定的file,并执行它。其他参数用法与execl()相同。

    • 示例:execlp("ls", "ls", "-l", "-a", NULL);PATH中查找ls命令并执行。

      示例给的有两个ls,这并不重复,第一个是告诉系统我要执行谁,第二个是告诉系统我想如何执行。

  3. execv()

    • 函数原型:int execv(const char *path, char *const argv[])

    • 功能:与execl()类似,但命令行参数以字符串数组的形式传递。

    • 示例:char *const argv[] = {"ls", "-l", "-a", NULL}; execv("/usr/bin/ls", argv);

      #include <stdio.h>
      #include <unistd.h>
      #include <assert.h>
      #include <sys/wait.h>
      #include <sys/types.h>
      #include <stdlib.h>
      int main()
      {printf("process is running...\n");pid_t id = fork();assert(id != -1);if (id == 0){char *const argv_[] = {"ls", "--color=auto", "-a", "-l", NULL}; execv("/usr/bin/ls", argv_); //通过字符数组传递参数}int status = 0;pid_t ret = waitpid(id, &status, 0);//等待子进程if (ret > 0) printf("wait success: sig: %d, exit code: %d\n", WEXITSTATUS(status), WIFEXITED(status) );printf("process running done......\n");return 0;
      }

      运行结果与上面的同。

  4. execvp()

    • 函数原型:int execvp(const char *file, char *const argv[])
    • 功能:结合了execv()execlp()的特点,在PATH中搜索指定的可执行文件,并以字符串数组的形式传递命令行参数。
    • 示例:char *const argv[] = {"ls", "-l", "-a", NULL}; execvp("ls", argv);
  5. execle()

    • 函数原型:int execle(const char *path, const char *arg, ..., char *const envp[])

    • 功能:除了指定程序路径和命令行参数外,还可以显式指定新程序的环境变量数组 envp

    • 示例:execle("/bin/ls", "ls", "-l", NULL, my_env); 其中 my_env 是自定义的环境变量数组。

      //mybin.c
      #include <stdio.h>
      #include <stdlib.h>
      int main() 
      {// 系统就有printf("PATH:%s\n", getenv("PATH"));printf("PWD:%s\n", getenv("PWD"));// 自定义printf("MYENV:%s\n", getenv("MYENV"));printf("另一个程序\n");printf("另一个程序\n");printf("另一个程序\n");printf("另一个程序\n");printf("另一个程序\n");printf("另一个程序\n");printf("另一个程序\n");return 0;
      }
      //test.c
      #include <stdio.h>
      #include <unistd.h>
      #include <assert.h>
      #include <sys/wait.h>
      #include <sys/types.h>
      #include <stdlib.h>
      int main()
      {printf("process is running...\n");pid_t id = fork();assert(id != -1);if (id == 0){char *const envp_[] = { (char*)"MYENV=123456789", NULL};putenv((char*)"MYENV=987654321");//将指定环境变量导入到系统中//execle("./mybin", "mybin", NULL, envp_);//自定义环境变量extern char **environ;execle("./mybin", "mybin", NULL, environ);}int status = 0;pid_t ret = waitpid(id, &status, 0);//等待子进程if (ret > 0) printf("wait success: sig: %d, exit code: %d\n", WEXITSTATUS(status), WIFEXITED(status) );printf("process running done......\n");return 0;
      }

      当使用自定义的环境变量时,子进程只会接收你传的环境变量数组。如下

      当传入系统的环境变量时,自定义的环境变量又传不过去,所以想要同时满足将系统环境变量传过去的同时也将自定义环境变量传过去,此时就可以使用putenv()函数。

综上得出如下规律:

  • l(list):表示参数采用列表
  • v(vector):参数用数组
  • p(path):有p表示自动搜索环境变量PATH
  • e(environ):表示自己维护环境变量

事实上除了上述5个函数之外,还有一个execve()函数,它与上述函数不同的是execve()是一个系统调用,其它五个函数最终都会调用execve()

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

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

相关文章

使用 JavaScript 的 XMLHttpRequest 或 Fetch API 发送 HTTP 请求时,GET 请求和 POST 请求处理参数的方式不同,这与 HTTP 协议的设计有关

使用 JavaScript 的 XMLHttpRequest 或 Fetch API 发送 HTTP 请求时,GET 请求和 POST 请求处理参数的方式不同,这与 HTTP 协议的设计有关 GET 请求的参数特点:GET 请求的参数通过 URL 传递。 原因: URL 表现方式:GET 请求的主要目的是从服务器获取资源。URL 是资源的唯一标…

IoU已经out了,试试这几个变体:GIoU、DIoU和CIoU介绍与对比分析

这是目标检测领域的首选评估指标。计算两个边界框的IoU时,如果它们有重叠区域,就测量重叠面积,然后除以两个框所覆盖的总面积。你是否曾经训练过一个模型,在评估指标上表现出色,但在实际可视化边界框时,却发现它在许多情况下都失败了?这可能是因为像简单交并比(IoU)这样的标准…

计算机是怎样跑起来的

总结自书籍:https://weread.qq.com/web/reader/b9b324005dd9f0b9b9e6f17k0e6320502c60e65972dc52f#outline?noScroll=10 前提 计算机的三个根本性基础计算机是执行输入、运算、输出的机器计算机的硬件由大量集成电路(IC)组成,每块IC都有许多引脚,用于输入/输出,IC在其内部…

2024-2025-1 20241428张雄一《计算机基础与程序设计》第九周学习总结

学期(如2024-2025-1) 学号20241428 《计算机基础与程序设计》第9周学习总结 作业信息这个作业属于哪个课程 <班级的链接>(如2024-2025-1-计算机基础与程序设计)这个作业的目标 操作系统责任、内存与进程管理、分时系统、CPU调度、文件、文件系统、文件保护、磁盘调度…

【CodeForces训练记录】CodeTON Round 9 (Div. 1 + Div. 2, Rated, Prizes!)

训练情况赛后反思 发现自己越来越能猜结论了,连续两题结论猜对了,一把rating上青了。 A题 构造一个数组使得模数互不相同,考虑构造一个模数为 \([0,1,2,3,4,5]\) 的数列,所以一个全是奇数的数列 \([1,3,5,7,9]\) 符合条件,直接输出 \(1 \sim n\) 的奇数即可。 #include &l…

Cellebrite UFED 4PC 7.71 发布下载 - Android 和 iOS 移动设备取证软件

Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件 The Industry Standard for Lawfully Accessing and Collecting Digital Data 请访问原文链接:https://sysin.org/blog/cellebr…

[BJDCTF2020]The mystery of ip 1

[BJDCTF2020]The mystery of ip 1 打开实例,发现flag.php路径,访问显示自己当前的内网iphackerbar添加xff请求头,尝试ip伪造,成功回显判断可能为xff注入,尝试sql的部分注入语句均无效,放弃sql注入,尝试SSTI模板注入 X-Forwarded-For: {1+1}成功回显,存在XFF-SSTI模板注…

[网鼎杯 2020 朱雀组]phpweb 1

[网鼎杯 2020 朱雀组]phpweb 1 打开实例,发现是个php页面,过了一会页面报错,发现参数func=date&p=Y-m-d h:i:s a看着像php传递函数执行的请求,尝试修改func为phpinfo func=phpinfo&p=Y-m-d h:i:s a可以看到参数被过滤了 采用highlight_file显示当前页面源代码,由于…

鸿蒙Next开发实战教程—电影app

最近忙忙活活写了不少教程,但是总感觉千篇一律,没什么意思,大家如果有感兴趣的项目可以私信给幽蓝君写一写。 今天分享一个电影App。这个项目也比较简单,主要是一些简单页面的开发和本地视频的播放以及横竖屏切换。 页面搭建以首页为例,很明显这是一个List页面,不过每一个…

担心360度评估结果隐私泄露怎么办?

当场惊呆!我们有个客户企业的hr反馈,公司内有领导的360评估结果分数比较垃垮。然后向下属施加淫威,从他们手里强制夺去手机看下面人给他的打分情况,毫无底线和节操。 古有邹忌讽齐王纳谏,今有360度评估,面对下属的反馈建议亦或批评,是打击报复还是接受批评与自我批评,…

.NET9 - 新功能体验(三)

.NET9和C#13引入Linq新方法CountBy和AggregateBy、序列化加强、Task.WhenEach方法、TimeSpan新重载、内置Swagger替换为Scalar,提升开发效率和代码可读性。书接上回,我们继续来聊聊.NET9和C#13带来的新变化。01、Linq新方法 CountBy 和 AggregateBy 引入了新的方法 CountBy 和…

用星球助手下载帖子的手把手教程

当我们想要把星球里的帖子和附件下载到本地电脑上慢慢学习时, 一篇一篇下载太麻烦了, 耗时且无聊. 用星球助手就非常方便啦. 打开软件后, 就是这样的界面.点击"新增", 输入星球名字和网页链接. 就像这样.最后, 就是点击"启动"开启一键下载了.帖子, 图片, 附…