函数的使用
当想使得某一个进程去运行其他的程序时,我们就可以使用exec类函数
当进程调用一种 exec 函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行(当前进程剩下的程序代码便不再执行)。调用 exec 并不创建新进程,所以调用 exec 前后该进程的id并未改变。
当函数调用失败时,返回值为-1,调用成功则无返回值
函数分类
exec类函数共有6种,只有execve是系统调用,六种函数的参数各不相同,逐个分析
'l':list,列表,调用带有l的exec函数,需要将参数全部列出来
'v':vector,数组,调用带有v的exec函数,需要将参数存到一个指针数组中,再把数组首地址给函数
'p':path,环境变量,调用带有p的exec函数,需要保证将要跳转到程序在环境变量PATH中(不再PATH中函数调用会失败)
'e':environment,环境变量,暂时不明白,待更新...(以下内容暂不涉及)
函数的参数,这是很多初学者都迷惑的地方
看不懂的可以结合后面的例子
参数除了特殊的空指针外,其余的都是字符串形式
第一个参数
对于execl,execv 为将要跳转的程序的路径(同时包括程序名),可以是相对路径,也可以是绝对路径
对于execlp,execvp则为将要跳转的程序的程序名(!!!只有程序名,但是只有目标程序在环境变量PATH中才可以跳转成功),也可以给出路径,这时候的效果就分别和上面两个函数一样
第二个参数及以后
首先需要普及一下,main函数是有参数的
int main(int argc,char* argv[])
剩下的参数其实是传递给目标程序的main函数(不需要传递argc,他是argv的大小,会自己计算),至少有一个非空,且最后要以NULL结尾,以便于实现程序间的交流,如果main函数中没有使用参数argv,那么参数其实可以随意写也可以直接用""
对于execl,execlp当然是将需要传递的参数全部列举在函数实参表里,不要忘了NULL
对于execv,execvp则需要将参数存在一个char类型的指针数组中(包括NULL),然后把指针数组首地址作为参数传递给execv类函数
下面是函数调用的示例,除了带e的没写,其他的都有:
关于环境PATH的查看和添加,可以参考blog:https://blog.csdn.net/qq_44786250/article/details/105325907
函数示例:
目标函数:
//test_1.c
#include<stdio.h>
int main()
{
printf("我是test_1\n");
return 0;
}
//test_2.c
#include<stdio.h>
int main(int argc,char*argv[])//argv为指针数组,用来存参数,argc为argv的大小,自动计算
{
printf("我是test_2\n");
for(int i=0;i<argc;i++)
printf("argv[%d]=%s\n",i,argv[i]);
return 0;
}
出击函数
//execl_1.c
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("execl_1执行test_1程序:\n");
if(execl("./test_1","",NULL)==-1)
//第一个参数指明路径:相对路径或绝对路径
//相对路径 ./为当前文件夹下,../为上一层文件夹
//后面为test_1中mian函数的参数,除NULL外至少有一个
//最后必须使用NULL结尾
perror("execl error");
//调用成功无返回值
//调用失败返回-1
printf("若exec成功,我不会被执行\n");
return 0;
}
//execl_2.c
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("execl_2执行test_2程序:\n");
if(execl("./test_2","Hello","Good morning","Bye",NULL)==-1)
perror("execl error");
printf("若exec成功,我不会被执行\n");
return 0;
}
//execv_1.c
#include<stdio.h>
#include<unistd.h>
int main()
{
char* buf[]={"",NULL};//将参数存到指针数组中,至少一个非空,且以空结尾
printf("execv_1执行test_1程序:\n");
if(execv("./test_1",buf)==-1)
//第一个参数还是路径
//第二个参数是指针数组名
//直接使用数组传递预先存好的参数
perror("execv error");
printf("若exec成功,我不会被执行\n");
return 0;
}
//execv_2.c
#include<stdio.h>
#include<unistd.h>
int main()
{
char* buf[]={"Hello","Good moring","Bye",NULL};
printf("execv_2执行test_2程序:\n");
if(execv("./test_2",buf)==-1)
perror("execv error");
printf("若exec成功,我不会被执行\n");
return 0;
}
//execlp_1.c
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("execlp_1执行 ls 指令:\n");
if(execlp("ls","",NULL)==-1)
//执行shell指令ls
//第一个参数应该是PATH中的可执行文件名
//不需要单独指明路径
//后面的参数与execl相同
perror("execlp error\n");
printf("如果exec成功,此句不会执行\n");
return 0;
}
//execlp_2.c
#include<stdio.h>
#include<unistd.h>
int main()
{
printf("execlp_2执行 test_2 程序:\n");
if(execlp("test_2","Hello","Good moring","Bye",NULL)==-1)
//执行程序 test_2
perror("execlp error\n");
printf("如果exec成功,此句不会执行\n");
return 0;
}
//execvp_1.c
#include<stdio.h>
#include<unistd.h>
int main()
{
char* buf[]={"",NULL};//将参数存到指针数组中,至少一个非空,且以空结尾
printf("execvp_1执行 ls 指令:\n");
if(execvp("ls",buf)==-1)
//第一个参数还是PATH中需要执行文件名
//第二个参数是指针数组名
//直接使用数组传递预先存好的参数
perror("execvp error");
printf("若exec成功,我不会被执行\n");
return 0;
}
//execvp_2.c
#include<stdio.h>
#include<unistd.h>
int main()
{
char* buf[]={"Hello","Good moring","Bye",NULL};
printf("execvp_2执行test_2程序:\n");
if(execvp("test_2",buf)==-1)
perror("execvp error");
printf("若exec成功,我不会被执行\n");
return 0;
}
在后续的博客中还有多进程配合exec函数的使用,欢迎大家观看和收藏