Linux系统中,我们可以使用可以使用system函数和exec系列的函数调用另一个可执行文件或调用命令。
exec系列函数简单介绍
#include <unistd.h>
extern char **environ;
int execl(const char *path, const char *arg, ... /* (char *) NULL */);
int execlp(const char *file, const char *arg, ... /* (char *) NULL */);
int execle(const char *path, const char *arg, ... /*, (char *) NULL, 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[]);
函数返回值:
成功: 函数不会返回
出错: 返回-1,失败原因记录在error中。
函数之间的区别
- 路径还是文件名
execl、execle、execv函数取路径作为参数,execlp、execvp、execvpe取文件名作为参数 - 参数表传递
函数execl、execlp、execle要求将新程序的每个命令行参数都说明为一个单独的参数,这种参数以空指针结束。
函数execv、execvp、execvpe应该先构造一个指向各个参数的指针数组,然后将该数组的地址作为函数的参数。 - 向新程序传递环境表
execle可以传递一个直线环境字符串指针数组的指针
其他的函数则使用进程中的environ变量为新程序复制现有的环境。
实验记录
- 带l 的exec函数:execl,execlp,execle,表示后边的参数以可变参数的形式给出且都以一个空指针结束。
示例:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("entering main process---\n");
execl("/bin/ls","ls","-l",NULL);
printf("exiting main process ----\n");
return 0;
}
2. 带 p 的exec函数:execlp,execvp,表示第一个参数path不用输入完整路径,只有给出命令名即可,它会在环境变量PATH当中查找命令
示例:带p但没给出完整路径
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("entering main process---\n");
execl("ls","ls","-al","~",(char *)0);
printf("exiting main process ----\n");
return 0;
}
结果:
现在带p:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("entering main process---\n");
execlp("ls","ls","-al","~",(char *)0);
printf("exiting main process ----\n");
return 0;
}
- 不带 l 的exec函数:execv,execvp表示命令所需的参数以char *arg[]形式给出且arg最后一个元素必须是NULL
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
printf("entering main process---\n");
int ret;
char *argv[] = {"ls","-l",NULL};
ret = execvp("ls",argv);
if(ret == -1)
perror("execl error");
printf("exiting main process ----\n");
return 0;
}
结果
- 带 e 的exec函数:execle表示,将环境变量传递给需要替换的进程
从上述的函数原型中我们发现:
extern char **environ;
此处的environ是一个指针数组,它当中的每一个指针指向的char为“XXX=XXX”
environ保存环境信息的数据可以env命令查看:
它由shell进程传递给当前进程,再由当前进程传递给替换的新进程。
示例:execle.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
//char * const envp[] = {"AA=11", "BB=22", NULL};
printf("Entering main ...\n");
int ret;
ret = execl("./hello", "hello", NULL);
//execle("./hello", "hello", NULL, envp);
if(ret == -1)
perror("execl error");
printf("Exiting main ...\n");
return 0;
}
hello.c
#include <unistd.h>
#include <stdio.h>
extern char** environ;
int main(void)
{
printf("hello pid=%d\n", getpid());
int i;
for (i=0; environ[i]!=NULL; ++i)
{
printf("%s\n", environ[i]);
}
return 0;
}
可知原进程确实将环境变量信息传递给了新进程
那么现在我们可以利用execle函数自己给的需要传递的环境变量信息:
示例程序:execle.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char * const envp[] = {"AA=11", "BB=22", NULL};
printf("Entering main ...\n");
int ret;
//ret =execl("./hello", "hello", NULL);
ret =execle("./hello", "hello", NULL, envp);
if(ret == -1)
perror("execl error");
printf("Exiting main ...\n");
return 0;
}
hello.c
#include <unistd.h>
#include <stdio.h>
extern char** environ;
int main(void)
{
printf("hello pid=%d\n", getpid());
int i;
for (i=0; environ[i]!=NULL; ++i)
{
printf("%s\n", environ[i]);
}
return 0;
}
结果:
确实将给定的环境变量传递过来了。
参考:
Linux execlp函数.
linux系统编程之进程(五):exec系列函数(execl,execlp,execle,execv,execvp)使用.