Linux多进程编程之exec函数族使用
- 1.exec函数族是什么
- 2.execl函数具体使用
- 3.execlp
- 4.exec后面不同字母所代表的含义
1.exec函数族是什么
顾名思义,它并不只是一个函数,而是以exec开头的六个函数,并且是没有exec这个函数的(就像TCP/IP协议族不只是TCP和IP两个协议一样):
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[]);
它们的作用就是在使用fork产生多进程之后,可以将子进程的进程空间替换成我们想要执行的程序,产生一个金蝉脱壳的效果。因为很多时候我们并不想让子进程一样的执行父进程的代码,因为子进程复制了父进程的进程空间,一样的代码和变量。而使用exec函数族则可以让子进程换成其它的可执行程序。
而在exec函数族当中,如上面的代码所示,最常用的起始就是前两个函数,execl和execlp。所以下面具体讲解前两个函数的具体用法,其它函数当然也会介绍如何使用。
2.execl函数具体使用
首先我们可以先生成一个可执行程序:
//hello.c
#include <stdio.h>
int main() {
printf("hello Ntt!\n");
return 0;
}
然后可以在Linux下编译一下:
sudo gcc hello.c -o hello
关于execl的解读:
int execl(const char *path, const char *arg, ...
/* (char *) NULL */);
第一个参数path代表的是可执行文件的路径,可以使用绝对路径或者相对路径,推荐使用绝对路径。后面的都是这个可执行文件的参数,以NULL作为结尾,这里注意,虽然我们hello程序没有其它的参数,但它本身就算参数的一部分,所以下面可见具体使用:
//excel.c
//CSDN Credic1017
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid = fork();
if(pid > 0) {
printf("I am parent process. and pid=%d, ppid=%d\n", getpid(), getppid());
sleep(1);
}else if(pid == 0) {
execl("hello", "hello", NULL);
//下面的代码不会执行
printf("I am child process. and pid=%d, ppid=%d\n", getpid(), getppid());
}
return 0;
}
编译一下:
sudo gcc excel.c -o excel
并且在return 0前面再放个打印语句,子进程也不会执行该打印语句,因为它的进程空间全部被替换了,替换成了我们的hello可执行程序。
这里的话还可以调用Linux本身的程序,比如查看系统进程状态 ps aux,那么这里同理,ps所在的位置可用which查看,ps作为第一个参数,aux作为第二个参数,都是以字符数组存在的参数,最后以NULL结尾。
//excel.c
//CSDN Credic1017
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
int main() {
pid_t pid = fork();
if(pid > 0) {
printf("I am parent process. and pid=%d, ppid=%d\n", getpid(), getppid());
sleep(1);
}else if(pid == 0) {
execl("/bin/ps", "ps", "aux", NULL);
//下面的代码不会执行
printf("I am child process. and pid=%d, ppid=%d\n", getpid(), getppid());
}
return 0;
}
3.execlp
int execlp(const char *file, const char *arg, ...
/* (char *) NULL */);
这里只讲和execl的区别,第一个参数由path改为了file,file直接就为需要执行的可执行文件的文件名,就比如hello,像之前的path,就是要选定文件的相对路径或者绝对路径。当然ps也是直接写的,而不是像之前的/bin/ps。后面的参数还是一样的。
execlp("ps", "ps", "aux", NULL);
它也会和之前的运行结果一样,主要是他会到环境变量中去找。如果环境变量没找到则返回失败的参数。
4.exec后面不同字母所代表的含义
前面在execl中已经使用了l,其实就是代表参数地址以空指针结尾,使用了参数地址列表。
p的话也介绍了,其实就是在可执行程序那块会自动调用环境变量,从而可以少写点路径名。
那再看到exec后面带v的一个用法:
//声明:
int execv(const char *path, char *const argv[]);
//使用:
char *argv = {"ps", "aux", NULL};
execv("/bin/ps", argv);
那再看到exec后面带e的一个用法:
对于e结尾的解读就是存有环境变量字符串地址的指针数组的地址。
#include <unistd.h>
int execve(const char *filename, char *const argv[],
char *const envp[]);
//使用:
char *const envp[] = {"/home/NTT", "/home/aaa", "/home/bbb"};
char *argv = {"ps", "aux", NULL};
execve("/bin/ps", argv, envp);
所以,结合exec后面每种字母代表的含义能正确的使用exec函数族,遇事不决找男人(man)。