exec 函数族

Posted guolongzyt

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了exec 函数族相关的知识,希望对你有一定的参考价值。

exec 函数族基本概念

函数族的概念

函数名不同,实现的功能相同或相似的函数

作用

exec 函数族的作用是根据指定的文件名或者路径找到可执行文件,可在进程内部执行一个可执行文件,这将会取代原本调用进程的内容

返回值

exec 函数族的函数执行成功后不会返回【因为原进程内容被替换了】,失败时返回 -1 ,然后从原程序的调用点接着往下执行

工作原理

从虚拟地址空间角度来看,内核区中进程id等信息不变,而用户区中的代码段等数据将改成exec参数中的可执行程序的数据

具体函数

execl, execlp, execle, execv, execvp, execvpe

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

常用函数解析

execl

  • int execl(const char *path, const char *arg, ...);

参数 :

  • path : 需要指定执行的文件路径或名称
  • arg : 字符串,表示执行指定可执行文件的参数(不止一个)
    【第一个参数一般没有作用,通常写执行的程序名称,从第二个参数开始将作为执行程序的参数列表,而最后要以 NULL 结尾】

execlp

  • int execlp(const char *file, const char *arg, ...);

区别 :execlp 函数将会在当前环境变量中对指定文件名进行查找,若指定文件为被配置为环境变量则查找不到(shell命令通常配置为环境变量)

参数 :

  • file : 需要执行的可执行文件名
  • arg : 与 execl 一致

更多

exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量

参考博客 https://blog.csdn.net/u014530704/article/details/73848573

exec函数族

exec函数族

fork()函数创建子进程后,子进程往往要调用一种e x e c函数以执行另一个程序。当进程调用一种exec函数时,该进程完全由新程序代换,而新程序则从其 ma i n函数开始执行。 因为调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用另一个新程序替换了当前进程的正文、数据、堆和栈段。 有六种不同的e x e c函数可供使用,它们常常被统称为exec函数。

#include<unistd.h>  
int execl(const char *pathname, const char * arg0,.../*(char*)0*/);  
int execv(const char *pathname, char *const argv[]);  
int execle(const char *pathname,const char * arg0,.../*(char*)0,char *const envp[]*/);  
int execve(const char *pathname, char *const argv[],char * const envp[]);  
int execlp(const char *filename, const char * arg0,.../*(char*)0*/);  
int execvp(const char *filename, char *const argv[]);  
//六个函数返回:若出错则为-1,若成功则不返回  

这些函数之间的第一个区别是前四个取路径名作为参数,后两个则取文件名作为参数。当指定filename作为参数时:

如果filename中包含/,则就将其视为路径名。否则就按PAT H环境变量,在有关目录中搜寻可执行文件。

PATH变量包含了一张目录表 (称为路径前缀),目录之间用冒号( : )分隔。例如下列na me = value环境字符串:

PATH = /bin:/usr/bin:/usr/local/bin: 指定在四个目录中进行搜索。(零长前缀也表示当前目录。在value的开始处可用:表示,在行中间则要用::表示,在行尾以:表示。)

如果execlp和execvp中的任意一个使用路径前缀中的一个找到了一个可执行文件,但是该文件不是由连接编辑程序产生的机器可执行代码文件,则就认为该文件是一个 shell脚本,于是 试着调用/bin/sh,并以该filename作为shell的输入。第二个区别与参数表的传递有关 ( l表示表( l i s t ),v表示矢量( v e c t o r ) )。函数execl、execlp和execle要求将新程序的每个命令行参数都说明为一个单独的参数。这种参数表以空指针结尾。

对于另外三个函数( execv, execvp和execve ),则应先构造一个指向各参数的指针数组,然后将该数组地址作为这三个函数的参数。 在使用ANSIC原型之前,对execl , execle和execlp三个函数表示命令行参数的一般方法是: char *arg 0, char *arg 1, ..., char *arg n, (char *) 0 应当特别指出的是:在最后一个命令行参数之后跟了一个空指针。如果用常数 0来表示一个空指针,则必须将它强制转换为一个字符指针,否则它将被解释为整型参数。如果一个整型数的长度与char *的长度不同,exec函数实际参数就将出错。 最后一个区别与向新程序传递环境表相关。以e结尾的两个函数( execle和execve)可以传递一个指向环境字符串指针数组的指针。其他四个函数则使用调用进程中的 environ变量为新程序复制现存的环境。通常,一个进程允许将其环境传播给其子进程,但有时也有这种情况,进程想要为子进程指定一个确定的环境。

例如,在初始化一个新登录的 shell时,login程序创建一个只定义少数几个变量的特殊环境,而在我们登录时,可以通过 shell启动文件,将其他变量加到环境中。

在使用 ANSI C原型之前, execle 的参数是:char * pathname, char *arg 0, ?, char *a rg n, (char *)0, char *envp[ ] 从中可见,最后一个参数是指向环境字符串的各字符指针构成的数组的指针。而在 ANSIC原型中,所有命令行参数,包括空指针,e n v p指针都用省略号(?)表示。 这六个e x e c函数的参数很难记忆。函数名中的字符会给我们一些帮助。字母 p表示该函数

取filename作为参数,并且用PATH环境变量寻找可执行文件。字母l表示该函数取一个参数表,它与字母v互斥。v表示该函数取一个arg v[ ]。最后,字母e表示该函数取e nvp[ ]数组,而不使用当前环境

这六个函数中只有一个execve是内核的系统调用。另外五个只是库函数,它们最终都要调用系统调用。这六个函数之间的关系示于图8 - 2中。在这种安排中,库函数 execlp 和execvp 使用PATH环境变量查找第一个包含名为filename的可执行文件的路径名前缀。

技术图片

 

技术图片

例1:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<unistd.h>
 4 
 5 int main(int argc,char * argv[])
 6 {
 7     if(argc<2)
 8     {
 9         perror("you haven‘t input the filename,please try again!
");
10         exit(EXIT_FAILURE);
11     }
12     if(execl("./create_file","create_file",argv[1],NULL)<0)
13         perror("execl error");
14 }

可以看见的是有一个名为create_file的可执行文件用于创建文件。在这里我们使用execl函数替换程序。

 技术图片

技术图片

例2:

代码:

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<unistd.h>
 4 
 5 int main(int argc,char * argv[])
 6 {
 7         if(argc<2)
 8         {
 9                 perror("you haven‘t input the filename,please try again!
");
10                 exit(EXIT_FAILURE);
11         }
12         if(execl("/bin/touch","touch",argv[1],NULL)<0)
13                 perror("execl error");
14 }                                                                

可以看见我们将exec2 成功的替换为了touch。并成功的执行了。

 技术图片

 

参考资料

Linux/Unix系统编程手册

Unix环境高级编程

Linux程序设计

以上是关于exec 函数族的主要内容,如果未能解决你的问题,请参考以下文章

exec函数族

进程控制---exec族函数

[Linux 高并发服务器] exec函数族

exec函数族

Linux 进程exec族函数详解

Linux系统编程——进程替换:exec 函数族