作用:当我们使用 fork 函数创建一个新的子进程后,子进程往往需要调用一种 exec 函数去执行另一个程序。当进程调用一种 exec 函数时,该进程执行的程序完全替换为新程序,而新程序则从其main函数开始执行。

注意:调用exec并不创建新进程,所以前后的进程ID并未改变。exec只是用磁盘上的一个新程序替换了当前进程的正文段、数据段、堆段和栈段。

exec函数共七种可供使用,(有了这些exec函数使得UNIX系统进程控制原语更加完善):

#include

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

int execle(const char *path, const char *arg, ..., char * const envp[]);

int execv(const char *path, char *const argv[]);

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

int execvp(const char *file, char *const argv[]);

int execvpe(const char *file, char *const argv[], char *const envp[]);

int fexecve(int fd, char *const argv[], char *const envp[]);

返回值:exec函数族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序的调用点接着往下执行。

参数说明: path:可执行文件的路径名字 arg:可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径且arg必须以NULL结束 file:如果参数file中包含/,则就将其视为路径名,否则就按 PATH环境变量,在它所指定的各目录中搜寻可执行文件。

异同点:一、前三个函数取路径名作为参数,后三个函数取文件名作为参数,最后一个则取文件描述符作为参数。

        1、如果file中包含 /,则就其视为路径名;否则就按照PATH环境变量,在它所指的各目录中搜寻可执行文件。

二、关于参数(l 表示列表list ,v表示矢量vector)。函数execl、execlp和execle 要求新程序的每个命令行参数都作为一个单独的参数。这种参数表以空指针(NULL)结尾。对于另外的函数则应先构造一个指向各参数的指针数组,然后将该数组的地址作为这4个函数的参数。(注:如果使用常量0来表示一个空指针,则必须强制转换成一个指针;否则将被解释为整型参数。)

exec函数的参数很难记忆。函数名中包含的字符会给我们一些帮助。

字母 p:表示该函数取filename作为参数,并且用PATH环境变量寻找可执行的文件。

字母 l:表示该函数取一个参数表,它与字母v互斥。

字母v:表示该函数取一个argv [ ]矢量。

字母 e: 表示该函数取 envp [ ]数组,而不使用当前环境。

/argecho.c //被调用函数

#include

int main(int argc, char** argv)

{

int i;

for(i=0;i

printf("argv[%d] : %s\n",i,argv[i]);

}

return 0;

}

 execl函数的实现:

#include

#include

int main()

{

printf("before execl:\n");

if(execl("./argecho","file1","file2",NULL) == -1){

printf("execl failed\n");

perror("execl:\n");

}

printf("after execl\n");

return 0;

}

运行结果:

 通过结果:

        1、exec函数在成功运行后,新程序将完全替换原函数,原函数剩下的部分将不会运行。

        2、exec函数在出错时会返回-1,并且设置errno。因此,可以调用perror函数对出错原因进行分析。

exec可以调用可执行程序,同样的也可以执行ls 、pwd 这样的指令。

通过调用whereis指令,寻找 date 指令的绝对路径:

#include

#include

int main()

{

printf("before execl:\n");

if(execl("/bin/date","date",NULL) == -1){

printf("execl failed\n");

perror("execl:\n");

}

printf("after execl\n");

return 0;

}

上述步骤中,需要调用 whereis 找到绝对路径后,才可在指定路径下调用新程序。若没有绝对路径,则会显示errno。

execlp函数的实现:

#include

#include

int main()

{

printf("before execl:\n");

if(execlp("date","date",NULL) == -1){

printf("execl failed\n");

perror("execl:\n");

}

printf("after execl\n");

return 0;

}

上述实验下,execlp函数带p,所以能通过环境变量PATH查找到可执行文件date。

execvp函数的实现:

带v与带l的属于互斥关系,两者的不同在于参数的表现形式。(带v 的函数应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。)

include

#include

int main()

{

printf("before execl:\n");

char* argv[] = {"date",NULL};

if(execvp("date",argv) == -1){

printf("execl failed\n");

perror("execl:\n");

}

printf("after execl\n");

return 0;

}

execle函数的使用:

#include //待执行函数

int main(int argc,char** argv)

{

int i;

char **ptr;

extern char **environ;

for(i=0;i

printf("argv[%d]:%s\n",i,argv[i]);

}

for(ptr = environ;*ptr != 0;ptr++){

printf("%s\n",*ptr);

}

return 0;

}

#include

#include

int main()

{

char *init_env[] = {"USER=unknown","PATH=/tmp",NULL};

pid_t pid;

if((pid = fork()) < 0){

printf("fork error\n");

}else if(pid == 0){

printf("before execle\n");

if(execle("./echoall","echoall","myargl","MY ARG2",NULL,init_env) < 0){

perror("execle\n");

}

printf("after execle\n");

}

waitpid(pid,NULL,0);

return 0;

}

结果:

 带有e的函数可以传递一个指向环境字符串指针数组的指针,通过这个地址可以改变新函数的环境变量。

总结:exec族函数的作用大体相同,区别在于所带参数的表现形式的不同,以及配置的功能些许不同。

Linux---关于环境变量(如何配置环境变量)

1、如何查找当前环境变量?

2、如何配置环境变量? 

例子:如需要将以下路径添加至环境变量

 

输入:export PATH=$PATH:需要添加的路径

随后再次输入echo $PATH,新的路径便添加进来了。

这样就可以在运行不在当前路径下,但是在环境变量当中的可执行文件了。

文章链接

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。