exec系列函数。都是以execl开头或者execv开头(l表示列表list,v表示矢量vector),exec()函数将当前进程映像替换为新的进程映像, 在ubuntu下 man execv
#includeextern 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[]);
下面两个是分别man execve和man fexecve之后出现的
int execve(const char *filename, char *const argv[], char *const envp[]); int fexecve(int fd, char *const argv[], char *const envp[]);
函数返回值:
成功: 函数不会返回
出错: 返回-1,失败原因记录在error中。
函数之间的区别是:
这些函数之间的第一个区别就是execl、execle、execv函数取路径作为参数,execlp、execvp、execvpe取文件名作为参数,当指定的filaname作为参数时: 1、如果filename中包含/,则将视为路径名 2、如果不包含/,则按照PATH环境变量,在它所指定的各个目录中搜寻可执行文件。 第二个区别与参数表的传递有关(l表示列表list,v表示矢量vector) 1、函数execl、execlp、execle要求将新程序的每个命令行参数都说明为一个单独的参数,这种参数以空指针结束。 2、函数execv、execvp、execvpe应该先构造一个指向各个参数的指针数组,然后将该数组的地址作为函数的参数。 在使用ISO C原型之前,对execl、execle、execlp三个函数的表示命令行参数的一般方法是: char *arg0, char *arg1, …, char *argn, (char *)0 需要在最后一个命令行参数之后跟一个char *的空指针,比如上面的表示方法(char *)0 如果不转换成(char *)的指针,那么exec函数的实际参数出错。 第三个区别与向新程序传递环境表有关。 1、execle可以传递一个直线环境字符串指针数组的指针 2、其他的函数则使用进程中的environ变量为新程序复制现有的环境。 通常,一个进程允许将其中环境传播给器子程序,但有时也会有,进程想要为子进程指定某一个确定的环境。在使用ISO C原型之前,execle的参数是:
char *path, char *arg0, ..., char *argn, (char *)0, char *envp[]
所以,最后一个参数时指向环境字符串的各个字符串构成的数组的指针 关于exec函数,其中名称中的不同字符代表不同的意思: 1、字母p标识改函数去filename作为参数,并且用PATH环境变量寻找你可执行的文件。 2、字母l表示该函数取一个参数表,与字母v互斥,v表示该函数取一个argv[]矢量。 3、字母e表示该函数取envp[]数组,而不是用当前环境。
在这种安排中,库函数execlp和execvp使用PATH环境变量,查找、第一个包含名为filename的可置信文件的路径名前缀,fexecv库函数使用/proc吧文件描述符参数转换为路径名,execve用该路径去执行程序。
下面的图片说明exec函数之间的关系(图片摘自UNIX环境高级编程 第三版):
下面的所有的测试代码均以调用新的程序为例。
首先,先编写一个简单的测试程序execTest.c,代码如下:
#includeint main(int argc, const char **argv) { int ret = 0, i = 0; for(i = 0; i 将execTest.c编译生成可执行文件execTest,运行程序,简单的效果如下所示:
1、execl函数测试,新建代码文件为execl.c,代码如下:
#include#include int main(int argc, const char **argv) { int retval = 0; if((retval = execl("/home/songtb/Desktop/songshuai/exec/test", "args0", "args1", "args2", (char *)0)) 将文件execl.c编译生成可执行文件execl,运行之后的效果为:
可以看出,调用的程序正常执行,并且没有打印出retval的值。
2、execlp函数的测试,新建文件execlp.c,代码如下:
#include#include extern char **environ; int main(int argc, const char **argv) { int retval = 0; if((retval = execlp("execTest", "abcd", "1234", "myTest", (char *)NULL)) 编译execlp.c生成可执行文件execlp,直接运行效果为:
可以看到提示错误,没有找到文件,那么将execlp中参数修改为如下:
if((retval = execlp("./execTest", "abcd", "1234", "myTest", (char *)NULL))再次编译执行,可以看出效果为:
3、execle函数的测试,新建文件execle.c,代码如下:
#include#include int main(int argc, const char **argv) { char *envp[] = {"USER=songshuai", "PATH=null", NULL}; if(execle("execTest", "abcd", "1234", "my Test", (char *)NULL, envp)) perror("execle return error "); return 0; } 编译execle.c生成可执行文件execle,直接运行效果为:
4、下面的这三个函数(execv、execvp、execvpe),做一个循环调用的效果,新建三个文件,代码分别为:
execv.c
#include#include #include int main(int argc, const char **argv) { time_t timep; time (&timep); char *args[] = {"execv1 args1", "execv2", NULL}; sleep(1); printf("I am execv, Time is : %s", ctime(&timep)); if(execv("execvp", args)) perror("execvp return error "); return 0; } execvp.c
#include#include #include int main(int argc, const char **argv) { time_t timep; time (&timep); char *args[] = {"execvp1 args1", "execvp2", NULL}; sleep(1); printf("I am execvp, Time is : %s", ctime(&timep)); if(execvp("./execvpe", args)) perror("execvp return error "); return 0; } execvpe.c
#include#include #include int main(int argc, const char **argv) { time_t timep; time (&timep); char *args[] = {"execvpe1 args1", "execvpe2", NULL}; char *envp[] = {"PATH=/home", "null2", NULL}; sleep(1); printf("I am execvpe, Time is : %s", ctime(&timep)); if(execvpe("./execv", args, envp)) perror("execvpe return error "); return 0; } 编译生成可执行文件,名称为execv、execvp、execvpe;
执行的效果为:
可以查看进程管理,这三个进程中每一次都只有以一个进程在运行;
以上就是
为各位朋友分享的 相关内容。想要了解更多Linux相关知识记得关注公众号“良许Linux”,或扫描下方二维码进行关注,更多 等着你!