网站合作建设方案,网站开发如何避开法律,网络营销推广与策划课后答案,网站建设里面包含什么语言本节学习exec族函数#xff0c;并大量参考了以下链接#xff1a; linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客 exec族函数函数的作用
我们用fork函数创建新进程后#xff0c;经常会在新进程中调用exec函数去执行另外一个程… 本节学习exec族函数并大量参考了以下链接 linux进程---exec族函数(execl, execlp, execle, execv, execvp, execvpe)_云英的博客-CSDN博客 exec族函数函数的作用
我们用fork函数创建新进程后经常会在新进程中调用exec函数去执行另外一个程序。当进程调用exec函数时该进程被完全替换为新程序。因为调用exec函数并不创建新进程所以前后进程的ID并没有改变。 同时由于exec族函数包含很多API所以一个个去Linux敲man可能有些麻烦可以直接去Linux官网的man Page来查看Linux man pages exec族函数中的具体函数介绍
exec族函数功能
在进程内部调用执行一个可执行文件。可执行文件既可以是二进制文件也可以是任何Linux下可执行的脚本文件。
函数族成员
execlexeclpexecleexecvexecvpexecvpe
函数原型
#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[]); //应用相对较少参数说明
path可执行文件的路径名字arg可执行程序所带的参数第一个参数为可执行文件名字没有带路径且arg必须以NULL结束file如果参数file中包含/则就将其视为路径名否则就按PATH环境变量在它所指定的各目录中搜寻可执行文件返回值exec函数族的函数执行成功后不会返回调用失败时会设置errno并返回-1然后从原程序的调用点接着往下执行
exec族函数参数极难记忆和分辨函数名中的字符会给我们一些帮助
l : 使用参数列表p使用文件名并从PATH环境进行寻找可执行文件v应先构造一个指向各参数的指针数组然后将该数组的地址作为这些函数的参数。e多了envp[]数组使用新的环境变量代替调用进程的环境变量
带 “l” 的一类exec函数l表示list 包括execl、execlp、execle要求将新程序的每个命令行参数都说明为 一个单独的参数。这种参数表以空指针结尾 通过execl举例
execl.c:
#include stdio.h
#include stdlib.h
#include unistd.hint main(void)
{printf(before execl\n);if(execl(./arg_go,aaa,bbb,NULL) -1){printf(execl failed!\n);perror(why); //用于判断错误}printf(after execl\n);return 0;
}
arg.c:
#include stdio.hint main(int argc,char *argv[])
{int i 0;for(i 0; i argc; i){printf(argv[%d]: %s\n,i,argv[i]); }return 0;
}
实现效果1 可见在运行了execl函数之后程序确实被完全替代成了另一个程序所以原程序最后的“after execl”并不会被打印 同时再次强调execl函数的第一个参数写的是执行文件而不是C文件所以运行主程序之前先编译并自己命名一个执行文件 那么既然execl可以使用可执行程序来完全替换一段程序那么系统的指令本质上也是一个个可执行文件就比如经常使用的 “ls” 通过“whereis ls”可以查看这个可执行文件的绝对路径 修改execl.c:
#include stdio.h
#include stdlib.h
#include unistd.hint main(void)
{printf(before execl\n);if(execl(/bin/ls,ls,-l,NULL) -1){printf(execl failed!\n);perror(why);}printf(after execl\n);return 0;
}
实现效果2 可见通过execl函数成功将原程序替换成了ls并且还附带了“-l” 的参数 带 “p” 的一类exec函数 包括execlp、execvp、execvpe如果参数file中包含/则就将其视为路径名否则就按 PATH环境变量在它所指定的各目录中搜寻可执行文件。举个例子PATH/bin:/usr/bin 通过execlp举例
execlp.c:
#include stdio.h
#include stdlib.h
#include unistd.hint main(void)
{printf(before execl\n);if(execlp(ls,ls,-l,NULL) -1){printf(execl failed!\n);perror(why);}printf(after execl\n);return 0;
}
实现效果 可见实现了和上面使用execl来替换“ls”相同的效果但是代码却有所区别execlp的第一个参数不需要输入绝对路径只需要输入可执行文件的名字就可以其原因就是execlp的第一个参数不是path而是file而file参数如同上面所说 “如果参数file中包含/则就将其视为路径名否则就按PATH环境变量在它所指定的各目录中搜寻可执行文件 ” 为了进一步对比区别可以将execl.c的代码中的这一句进行修改第一个参数也改成“ls” if(execl(ls,ls,-l,NULL) -1) 然后运行execl.c 显然这再次说明了对于execl来说这种直接写可执行文件名字的方式不可取 环境变量的概念穿插
另外此处引出了“环境变量的概念在Linux中可以用 “echo $PATH” 来查看环境变量 也就是说只要可执行文件在上图的这些环境变量路径下那么只要调用带 “p” 的exec族函数第一个file参数就可以直接写可执行文件的名字了
Q那如何将新的路径配置到环境变量中去
A使用export指令“export PATH$PATH:想要添加的路径”
使用 “pwd” 显示当前路径 然后使用 “export PATH$PATH:/home/mjm/JC” 将当前路径添加到环境变量 此时如果修改 execlp.c 的代码
#include stdio.h
#include stdlib.h
#include unistd.hint main(void)
{printf(before execl\n);if(execlp(arg_go,aaa,bbb,NULL) -1){printf(execl failed!\n);perror(why);}printf(after execl\n);return 0;
}
执行代码 可见由于此时当前路径被添加到了环境变量中所以使用execlp函数并将第一个参数直接写成当前路径下的可执行文件也可以成功运行 带 “v” 不带 “l” 的一类exec函数 包括execv、execvp、execve应先构造一个指向各参数的指针数组然后将该数组的地址作为这些函数的参数 通过execv举例
execv.c:
#include stdio.h
#include stdlib.h
#include unistd.hint main(void)
{printf(before execl\n);char *argv[] {ls,-l,NULL};if(execv(/bin/ls,argv) -1){printf(execl failed!\n);perror(why);}printf(after execl\n);return 0;
}
可见唯一的区别就是“先构造了一个指向各参数的指针数组 ”
实现效果 可见同样实现了将“ls”替换原程序的效果并且也增加了“-l” 的参数 带 “e” 的一类exec函数 (应用相对较少) 包括execle、execvpe可以传递一个指向环境字符串指针数组的指针 由于相对比较复杂且初学时并不常用所以不做介绍可以去本节开头的链接去学习相关概念。