补充一下exec函数族:首先回顾一下
fork函数是用于创建一个子进程,该子进程几乎是父进程的副本,而有时我们希望子进程去执行另外的程序,exec函数族就提供了一个在进程中启动另一个程序执行的方法。
int execl(const char *path, const char *arg, ...)
int execv(const char *path, char *const argv[])
int execle(const char *path, const char *arg, ..., char *const envp[])
int execve(const char *path, char *const argv[], char *const envp[])
int execlp(const char *file, const char *arg, ...)
int execvp(const char *file, char *const argv[])
首先,前四个函数取path路径名作为参数,后两个取file;文件名作为参数。
第二参数表的传递:l表示列表,v表示矢量。带l的三个函数,要求将新程序的每个命令行参数都说明为一个单独的参数。其它三个函数,则应该构造一个指向各参数的指针数组,将该数组作为这些函数的参数。下面例程,你会看到这种区别的。
最后,带e的函数,可以传递一个指向环境字符串指针数组的指针,一般不用给NULL作为参数。
一点记忆的小技巧:p字符表示该函数去filename做参数。l表示该函数取一个参数表与字母v是互斥的。v表示取一个argv[]矢量。字母e表示该函数取envp[]数组,而不使用当前环境。
一个使用6个函数的例程
#include<stdio.h>
#include<uistd.h>
#include<stdlib.h>
int main()
{
char *argv1[]={"hello","NULL"}; //随便写一个hello.c的小程序,用来调用
char *argv2[]={"ls","-l","NULL"}; //小知识:linux下的命令其实也是相当于一个程序
if(fork()==0){ //子进程1,调用execl函数执行hello程序
if(execl("/home/hello","hello",NULL)<0){
perror("execl err");
exit(1);
}
}
if(fork()==0){ //子进程2,调用execv函数执行hello程序
if(execv("/home/hello",argv1)<0){
perror("execv err");
exit(1);
}
}
if(fork()==0){ //子进程3,调用execlp函数执行ls程序
if(execlp("ls","ls","-l",NULL)<0){
perror("execlp err");
exit(1);
}
}
if(fork()==0){ //子进程4,调用execvp函数执行ls程序
if(execvp("ls",argv2)<0){
perror("execvp err");
exit(1);
}
}
if(fork()==0){ //子进程5,调用execle函数执行ls程序
if(execle("/bin/ls","ls","-l",NULL,NULL)<0){
perror("execle err");
exit(1);
}
}
if(fork() == 0){ //子进程6,调用execve函数执行ls程序
if(execve("/bin/ls",argv2,NULL) <0){
perror("execve error");
exit(1);
}
}
return 0;
}
你可以看到,带l的函数每个命令行参数都是单独说明的。