Linux中,exec函数族有6种不同的调用的形式,它们声明在<unistd.h>头文件中,6个函数如下:
#include <unistd.h> int execve(const char *path,char* const argv[],char* const envp[]); int execv(const char *path,char* const envp[]); int execle(const char *path,const char *arg,...); int execl(const char *path,const char *arg,...); int execvp(const char *file,char* const argv[]); int execlp(const char *file,const char *arg,...);
exec调用并没有生成新进程。一个进程一旦调用exec函数,它本身就“死亡”了,系统把代码段替换成新的程序的
代码,废弃了原有的数据段和堆栈段,并为新程序分配新的数据段与堆栈段,惟一保留的就是进程ID。对系统而言,
还是同一个进程,不过执行的是另一个程序了。
为了更好的理解exec函数族的使用,需要先理解环境变量。为了便于用户灵活的使用shell,Linux引入了环境变量
的概念,包括用户的主目录、终端类型、当前目录等,它们定义了用户的工作环境,所以称为环境变量。用户可以使
用env命令查看环境变量值,用户也可以修改这些变量值以定制自己的工作环境。
下面是exec函数族的各个函数是如何将main函数需要的参数传递给它的:
- execv函数:execv函数通过路径名方式调用可执行文件作为新的进程映像。它的argv参数用来提供给main函数的
argv参数。argv参数是一个以NULL结尾(最后一个元素必须是一个空指针)的字符串数组。
- execve函数:在该系统调用中,参数path是将要执行的程序的路径名,参数argv、envp与main函数的argv、envp
对应。(参数argv和参数envp的大小都是受限制的。linux操作系统通过宏ARG_MAX来限制它们的大小,如果它们的容
量之和超过ARG_MAX定义的值将会发生错误。)
- execl函数:该函数与execv函数的用法类似。只是在传递argv参数的时候,每个命令行参数都声明为一个单独的
参数(参数中使用“...”说明参数的个数是不确定的),需要注意的是这些参数是以一个空指针作为结束的。
- execle函数:该函数与execl函数用法类似,只是要显式指定环境变量。环境变量位于命令行参数最后一个参数的
后面,也就是位于空指针之后。
- execvp函数:该函数与execv函数用法类似,不同的是参数filename。该参数如果包含"/",就相当于路径名;如
果不包含"/",函数就到PATH环境变量定义的目录中寻找可执行文件。
- execlp函数:该函数类似于execl函数,它们的区别和execvp与execv的区别一样。
exec函数族的6个函数中只有execve是系统调用。其它5个函数都是库函数,它们实现时都调用了execve。正常情况
下,这些函数是不会返回的,因为进程的执行映像已经被替换,没有接收返回值的地方了。如果有一个错误的事件,将
会返回-1。这些错误通常是由文件名或参数错误引起的。
exec函数族的作用是根据指定的文件名找到可执行文件,并用它来取代调用进程的内容,换句话说,就是在调用进
程内部执行一个可执行文件。这里的可执行文件既可以是二进制文件,也可以是任何Linux下可执行的脚本文件。