P11 Linux进程编程exec族函数

2023-12-10 14:52
文章标签 linux 函数 编程 进程 exec p11

本文主要是介绍P11 Linux进程编程exec族函数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言    

                  

🎬 个人主页:@ChenPi

🐻推荐专栏1: 《Linux C应用编程(概念类)_@ChenPi的博客-CSDN博客》✨✨✨ 

🔥 推荐专栏2: 《C++_@ChenPi的博客-CSDN博客》✨✨✨

🛸推荐专栏3: ​​​​​​《链表_@ChenPi的博客-CSDN博客 》 ✨✨✨
🌺本篇简介  :  Linux进程在运行中我们如何进入到另一个进程呢?

                         我们可以使用exec系统调用

Linux 是一个多用户多任务的操作系统,每个用户可以同时运行多个程序

进程是程序运行的主体,包括进程的创建,调度和消亡的整个过程

当用户执行一个指令或者启动一个程序时,就创建了一个进程

一个运行的程序也可能有多个进程。

每个进程将被分配各种资源    

一 exec族函数

1.1 exec族函数函数的作用:

我们用fork函数创建新进程后,经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时,该进程被完全替换为新程序。因为调用exec函数并不创建新进程,所以前后进程的ID并没有改变。

1.2 exec函数族分别是:execl, execlp, execle, execv, execvp, execvpe
函数原型:

#include <unistd.h> extern char **environ; int execl(const char *path, const char *arg, ... /* (char *) NULL */); 
int execlp(const char *file, const char *arg, ... /* (char *) NULL */); 
int execle(const char *path, const char *arg, ... /*, (char *) NULL, char * const envp[] */); 
int execv(const char *path, char *const argv[]); 
int execvp(const char *file, char *const argv[]); 
int execvpe(const char *file, char *const argv[], char *const envp[]); 
  • 返回值:
  • exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。
  • 参数说明:
  • path:可执行文件的路径名字
  • arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束
  • file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。

1.3 exec族函数的区别  

1.3.1 execl()和 execv()的区别

execl()和 execv()都是基本的 exec 函数,都可用于执行一个新程序,它们之间的区别在于:

参数格式不同,参数 path 意义和格式都相同,指向新程序的路径名,既可以是绝对路径、也可以是相对路径。execl()和 execv()不同的在于第二个参数,execv()的argv 参数与 execve()的 argv 参数相同,也是字符串指针数组;而 execl()把参数列表依次排列,使 用可变参数形式传递,本质上也是多个字符串,以 NULL 结尾,如下所示:

// execv 传参 
char *arg_arr[5]; 
/*参数 argv 则指定了传递给新程序的命令行参数。是一个字符串数组,
该数组对应于 main(int argc, char *argv[])函数的第二个参数 argv,
且格式也与之相同,是由字符串指针所组成的数组,以 NULL 结束。*/argv[0]对应的便是新程序自身路径名。 
arg_arr[0] = "./newApp"; 
arg_arr[1] = "Hello"; 
arg_arr[2] = "World"; 
arg_arr[3] = NULL; 
execv("./newApp", arg_arr); // execl 传参 
execl("./newApp", "./newApp", "Hello", "World", NULL); 

1.3.2 execlp()和 execvp()的区别

execlp()和 execvp()在 execl()和 execv()基础上加了一个 p,这个 p 其实表示的是 PATH;execl()和execv()要求提供新程序的路径名,而 execlp()和 execvp()则允许只提供新程序文件名,系统会在由 环境变量 PATH 所指定的目录列表中寻找相应的可执行文件,如果执行的新程序是一个 Linux 命 令,这将很有用;当然,execlp()和 execvp()函数也兼容相对路径和绝对路径的方式。

1.3.1 execle()和 execve()的区别

execle()和 execvpe()这两个函数在命名上加了一个 e,这个 e 其实表示的是 environment 环境变量, 意味着这两个函数可以指定自定义的环境变量列表给新程序,参数envp与系统调用execve()的envp参数相同,也是字符串指针数组,使用方式如下所示:

// execvpe 传参 
char *env_arr[5] = {"NAME=app", "AGE=25", "SEX=man", NULL}; 
char *arg_arr[5]; arg_arr[0] = "./newApp"; 
arg_arr[1] = "Hello"; 
arg_arr[2] = "World";
arg_arr[3] = NULL;
execvpe("./newApp", arg_arr, env_arr); // execle 传参 
execle("./newApp", "./newApp", "Hello", "World", NULL, env_arr); 

二 exec族函数使用示例

6 个 exec 库函数运行 ls 命令,并加入参数-li。

2.1 execl

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char ret = execl("/bin/ls","ls","-li",NULL);if(-1 == ret)  //调用失败返回-1perror("");
}

2.2 execv

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char *canshu[] = {"ls","-li",NULL};execv("/bin/ls",canshu);
}

2.3 execlp

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{execlp("ls","ls","-li",NULL);
}

2.4 execvp

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char *canshu[] = {"ls","-li",NULL};execvp("ls",canshu);
}

2.5 execle

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
char *env_init[] = {"AA=aa","BB=bb",NULL};  //作为参数传到下个执行文件void main()
{execle("./test","test",NULL,env_init);}

2.6 execve

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>void main()
{char *env_init[] = {"AA=aa","BB=bb",NULL};  //作为参数传到下个执行文件char *canshu[] = {"test","-li",NULL};execve("./test",canshu,env_init);}

 2.7 总结: 

  • l : 使用参数列表
  • p:使用文件名,并从PATH环境进行寻找可执行文件
  • v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
  • e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

这篇关于P11 Linux进程编程exec族函数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/477414

相关文章

Linux换行符的使用方法详解

《Linux换行符的使用方法详解》本文介绍了Linux中常用的换行符LF及其在文件中的表示,展示了如何使用sed命令替换换行符,并列举了与换行符处理相关的Linux命令,通过代码讲解的非常详细,需要的... 目录简介检测文件中的换行符使用 cat -A 查看换行符使用 od -c 检查字符换行符格式转换将

Linux系统配置NAT网络模式的详细步骤(附图文)

《Linux系统配置NAT网络模式的详细步骤(附图文)》本文详细指导如何在VMware环境下配置NAT网络模式,包括设置主机和虚拟机的IP地址、网关,以及针对Linux和Windows系统的具体步骤,... 目录一、配置NAT网络模式二、设置虚拟机交换机网关2.1 打开虚拟机2.2 管理员授权2.3 设置子

揭秘Python Socket网络编程的7种硬核用法

《揭秘PythonSocket网络编程的7种硬核用法》Socket不仅能做聊天室,还能干一大堆硬核操作,这篇文章就带大家看看Python网络编程的7种超实用玩法,感兴趣的小伙伴可以跟随小编一起... 目录1.端口扫描器:探测开放端口2.简易 HTTP 服务器:10 秒搭个网页3.局域网游戏:多人联机对战4.

Linux系统中卸载与安装JDK的详细教程

《Linux系统中卸载与安装JDK的详细教程》本文详细介绍了如何在Linux系统中通过Xshell和Xftp工具连接与传输文件,然后进行JDK的安装与卸载,安装步骤包括连接Linux、传输JDK安装包... 目录1、卸载1.1 linux删除自带的JDK1.2 Linux上卸载自己安装的JDK2、安装2.1

Kotlin 作用域函数apply、let、run、with、also使用指南

《Kotlin作用域函数apply、let、run、with、also使用指南》在Kotlin开发中,作用域函数(ScopeFunctions)是一组能让代码更简洁、更函数式的高阶函数,本文将... 目录一、引言:为什么需要作用域函数?二、作用域函China编程数详解1. apply:对象配置的 “流式构建器”最

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

Linux卸载自带jdk并安装新jdk版本的图文教程

《Linux卸载自带jdk并安装新jdk版本的图文教程》在Linux系统中,有时需要卸载预装的OpenJDK并安装特定版本的JDK,例如JDK1.8,所以本文给大家详细介绍了Linux卸载自带jdk并... 目录Ⅰ、卸载自带jdkⅡ、安装新版jdkⅠ、卸载自带jdk1、输入命令查看旧jdkrpm -qa

Linux samba共享慢的原因及解决方案

《Linuxsamba共享慢的原因及解决方案》:本文主要介绍Linuxsamba共享慢的原因及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录linux samba共享慢原因及解决问题表现原因解决办法总结Linandroidux samba共享慢原因及解决

新特性抢先看! Ubuntu 25.04 Beta 发布:Linux 6.14 内核

《新特性抢先看!Ubuntu25.04Beta发布:Linux6.14内核》Canonical公司近日发布了Ubuntu25.04Beta版,这一版本被赋予了一个活泼的代号——“Plu... Canonical 昨日(3 月 27 日)放出了 Beta 版 Ubuntu 25.04 系统镜像,代号“Pluc

Android Kotlin 高阶函数详解及其在协程中的应用小结

《AndroidKotlin高阶函数详解及其在协程中的应用小结》高阶函数是Kotlin中的一个重要特性,它能够将函数作为一等公民(First-ClassCitizen),使得代码更加简洁、灵活和可... 目录1. 引言2. 什么是高阶函数?3. 高阶函数的基础用法3.1 传递函数作为参数3.2 Lambda