exec用被执行的程序(调用的新程序)替换调用他(原程序)的程序,相比于fork函数创建一个心进程会产生一个新的PID,exec会启动一个新程序来替换当前的程序,且PID值不变。exec族函数有6种形式,我们一起来学习下吧。
#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[]);
先来学习下execl函数,要用它首先要从函数原型看懂每一个位置要传递什么类型的数据
int execl(const char *path, const char *arg, ...);
参数path指向要执行的文件路径(可以是命令的全路径、执行程序的全路径或脚本文件的全路径),后面的参数(arg及其后面的省略号)代表执行程序时传递的参数列表,并且第一个被认为是argv[0](即path路径后的第一个参数被认为是argv[0]),第二个被认为argv[1]。
main函数的原型为int main(int argc,char **argv),其中argv[0]是程序的名称程序需要的参数是从argv[1]才开始获取的,execl的argv[0]也是按照此习惯(法则),即argv[1]才是传给要启动程序的第一个参数,此处的argv[0]只是要传递的一个参数,对于大多数程序来说并没有实际意义,可以随便传一个字符串。但是不能写NULL,写NULL就代表传参列表结束了,后面再写参数程序也不会调用。对于自定义的程序,则要视情况而定,如果定义的程序argv[0]为一个重要的参数,有其实际的意义,此时就不能乱输了。大家只需记住紧跟path路径后的参数相当于main函数中的argv[0],函数的最后一个参数必须用NULL来作为结束标志。函数成功时不返回值,失败时返回-1,失败原因存在于errno中,可用perror()打印出错原因进行纠错。
下面用实例来感受一下:
1.使用execl执行不带选项命令的程序pwd
#include <unistd.h>
// extern char **environ;
// int execl(const char *path, const char *arg, ...);
int main()
{
execl("/bin/pwd","pwd",NULL);
return 0;
}
执行结果为打印当前路径,这和执行pwd命令是一样的。
2.使用execl执行带选项的命令程序ls
#include <unistd.h>
// extern char **environ;
// int execl(const char *path, const char *arg, ...);
int main()
{
/*argv[0]传入的是程序名ls,argv[1]传入-al指令,argv[2]传入的是
要查看的文件路径/home/CLC/file/file */
execl("/bin/ls","ls","-al","/home/CLC/file/file",NULL);
return 0;
}
执行结果如下图,与执行ls -al结果一样
我们学习使用execl函数主要还是要学会熟练调用我们自己编写的程序的,下面一个实例来演示下如何调用我们自己的程序:
#include <unistd.h>
// extern char **environ;
// int execl(const char *path, const char *arg, ...);
int main()
{
execl("/home/CLC/file/file/file1","kdfjk",NULL);
return 0;
}
这段代码调用了/home/CLC/file/file路径下的file1这个可执行文件,向第二个参数argv[0]传递了一个字符串,以NULL结尾。file1的代码内容为创建一个新的文件,execl函数的执行结果为调用execl函数的结果,因为这段代码只是来测试execl调用程序,并无其他操作,所以和直接执行./file1结果并无差别。
下面来分享一下execlp函数的用法
其函数原型为
int execlp(const char *file, const char *arg, ...);
execlp函数会从PATH环境变量所指的目录中查找符合参数file的文件名,找到后变执行该文件,将第二个以后的的参数当做该文件的argv[0]、argv[1]......,最后一个参数用NULL作为结束标志。
如果执行成功,则函数不会返回,执行失败则返回-1,失败原因存于errno中。
实践实例如下:
使用execlp执行不带选项的命令程序pwd
#include <unistd.h>
// int execlp(const char *file, const char *arg, ...);
int main(int argc,char **argv)
{
execlp("pwd","pwd",NULL);
return 0;
}
execlp的第一个参数直接用pwd这个命令即可,并不需要写出其全部路径,因为环境变量PATH中已经包含了路径/user/bin了,pwd就在这个路径下。
这段代码的执行结果为
相比execl函数需要写明路径,这个函数就方便很多了,但我们都要熟练掌握他们的用法鸭!