linux系统编程-exec函数族
exec函数族
- fork创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec函数以执行另一个程序。
- 当进程调用一种exec函数时,该进程的用户空间代码和数据完全被新程序替换,从新程序的启动例程开始执行。
- 调用exec并不创建新进程,所以调用exec前后该进程的id并未改变。
execlp函数
- int execlp(const char *file, const char *arg, …):加载一个进程,借助PATH环境变量
- 参数1:要加载的程序的名字(该参数需要配合PATH环境变量来使用,当PATH中所有目录搜索后没 有参数1则出错返回)
- 参数 2、3…:argv[0]、argv[2]、…NULL(必须以NULL结尾)
- 该函数通常用来调用系统程序。如:ls、date、cp、cat等命令。
实例代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
pid = fork();
if(pid<0)
{
perror("fork error");
exit(1);
}
else if(pid>1)
{
printf("i am parent");
sleep(1);
}
else
{
int tmp = execlp("ls","ls","-l","-a",NULL); //子进程执行 ls -al 命令
if(tmp<0)
exit(1);
}
return 0;
}
结果:运行app程序 和 运行 ls -al 命令结果一样
execl函数
- int execl(const char *path, const char *arg, …):加载一个进程, 通过 路径来加载。
- 对比execlp,如加载 “ls” 命令带有-l,-F参数
execlp(“ls”, “ls”, “-l”, “-F”, NULL); 使用程序名在PATH中搜索。
execl("/bin/ls", “ls”, “-l”, “-F”, NULL); 使用参数1给出的绝对路径搜索。
execle函数
- int execle(const char *path, const char *arg, …, char *const envp[] ):使用路径调用程序,使用新的环境变量数组设置被调用的程序的环境变量
hello.c : 输出自己pid和环境变量
#include <stdio.h>
#include <unistd.h>
extern char** environ;
int main(void)
{
printf("hello pid is:%d \n" ,getpid() );
int i;
for(i=0;environ[i];i++)
printf("%s\n",environ[i]);
return 0;
}
直接运行的结果:
app.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
int main(void)
{
pid_t pid;
pid = fork();
if(pid<0)
{
perror("fork error");
exit(1);
}
else if(pid>1)
{
printf("i am parent\n");
sleep(1);
}
else
{
char* envp[]={"AA=BBCCDD",NULL};
int tmp = execle("./xx/hello","app1",NULL,envp); //hello 上面的程序
if(tmp<0)
{
exit(1);
printf("child dead");
}
}
return 0;
}
执行结果: hello 进程的 环境变量 变成 AA=BBCCDD
execv函数
- int execv(const char *path, char *const argv[]);
char* argv[]={"ls", "-l","-a","NULL"};
execv("/bin/ls",argv);
execvp函数
- int execvp(const char *file, char *const argv[]) :
char* argv[]={"ls", "-l","-a","NULL"};
execv("ls",argv);// ls借助PATH环境变量
execve函数
- int execve(const char *path, char *const argv[], char *const envp[])
小结
- 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 execve(const char *path, char *const argv[], char *const envp[]);
(1)
- path:传递的是可执行程序的路径
- file:可执行程序名,依靠环境变量来找
- arg:传递 “argv[0]” ,“argv[1]”,…NULL
- argv[]: 定义一个字符串指针数组(命令行参数) 传进去 :char* argv[]={“ls”, “-l”,"-a",“NULL”};:
- envp[]: 定义一个字符串指针数组(环境变量) 传进去: char* envp[]={“AA=BBCCDD”,NULL};
(2)
- l (list) 命令行参数列表
- p (path) 搜素file时使用path变量
- v (vector) 使用命令行参数数组
- e (environment) 使用环境变量数组 ,不使用进程原有的环境变量,设置新加载程序运行的环境变量
(3)
- 事实上,只有execve是真正的系统调用,其它五个函数最终都调用execve,所以execve在man手册第2节,其它函数在man手册第3节。这些函数之间的关系如下图所示。