李代桃僵。
试想有一天,你带着老婆,出了城,吃着火锅,唱着歌,突然就被麻匪劫了。
当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
#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[]);
#include <unistd.h>
int execve(const char *filename, char *const argv[], char *const envp[]); //真正的系统调用,其他都是由它封装出来的。
这些函数如果调用成功则加载新的程序从启动代码开始执行,不再返回,如果调用出错则返回-1,所以exec函数只有出错的返回值而没有成功的返回值。
带有字母l(表示list)的exec函数要求新程序的每个命令行参数都当作一个参数传给它,命令行参数的个数是可变的,最后一个可变参数应该是NULL,起sentinel(哨兵)的作用。
对于带有字母v(表示vector)的函数,则应该先构造一个指向个参数的指针数组,然后将该数组的首地址当作参数传给它,数组中的最后一个指针也应该是NULL,就像main函数的argv参数或者环境变量表一样。
不带字母p(表示path)的exec函数第一个参数必须是程序的相对路径或绝对路径,例如”/bin/ls"或"./a.out"。
对于带字母p的函数:如果参数中包含/,则将其视为路径名。否则市委不带路径的程序名,在PATH环境变量的目录列表中搜索这个程序。
对于以e(表示environment)为结尾的exec函数,可以把一份新的环境变量表传给它,其他exec函数仍使用当前的环境变量表执行新程序。
用exec函数族,将ls命令接管,代码演示如下:
#include "./common/head.h"
/*功能:
*用exec函数族,接管ls -a -l命令。
*/
int main()
{
execl("/bin/ls", "ls", "-a", "-l", NULL); //第一个参数是ls命令的路径,后面的参数是ls的参数,注意第0个参数是ls(在执行ls -al时,ls这个参数并没有被解析,所以传什么都行),最后一个参数NULL起哨兵作用
//如果exec被正确执行,则运行不到这里,此进程已经被ls接管。若不成功,则会打印出错信息
perror("exec");
exit(1);
#if 0
//这里用execv实现和上面一样的功能
char *arr[] = {"ls", "-a", "-l", NULL}; //ls位置可以传任意值,NULL是哨兵
execv("/bin/ls", arr);
perror("exec");
exit(1);
#endif
return 0;
}