exec族函数的作用:
我们用fork函数创建新进程后,经常会在新进程中调用exec族函数去执行新的程序;当该进程调用exec族函数时,该进程被替代为新程序,因为exec族函数并不创建新进程,所以前后进程ID并未改变。
1、为什么要用exec族函数?
(1) 在网络服务器进程中常见的父进程等待客户端服务请求;父进程希望复制自己,使得父子进程可以执行不同的程序完需求。用在此场景中,父进程可以不断的等待客户的接入,同时创建子进程去完成对客户端的对接。
(2)在一个进程内部被调用执行一个可执行文件,可执行文件可以是二进制文件,也可以是Linux底下可执行的脚本文件。
2、exec族函数的返回值
由此可见:exec族的函数执行成功后不会返回,调用失败时,会设置errno并返回-1,然后从原程序调用点接着往下执行。
3、exec族函数原型:
#include <unistd.h>
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 execvpe(const char *file, char *const argv[],
4、exec族函数参数说明
path: 可执行文件的路径
arg : 可执行程序所带的参数,第一个参数为可执行文件名字,没有带路径
且arg必须NULL结束。
File: 如果参数file中包含/,则就将其视为路径名,否则按PATH环境变量,
在它所指定的各目录搜寻可执行文件。
exec族函数参数极难记忆和分辨,函数名中的字符会给我们一些帮助:
l : 使用参数列表
p:使用文件名,并从PATH环境进行寻找可执行文件
v:应先构造一个指向各参数的指针数组,然后将该数组的地址作为这些函数的参数。
e:多了envp[]数组,使用新的环境变量代替调用进程的环境变量
5、exacl 函数"
**主程序 :execl.c **
demo:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
if(execl("./main",argv[1],argv[2],argv[3],NULL) == -1){
printf("execl faill\n");
perror("why:");
}
printf("execl faill\n");
system("pause");
return 0;
}
被调程序:main.c
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
printf("argv[0]=%s\n",argv[0]);
printf("argv[1]=%s\n",argv[1]);
printf("argv[2]=%s\n",argv[2]);
system("pause");
return 0;
}
结果显示:
CLC@Embed_Learn:~$ ./execl main aa bbb
argv[0]=main
argv[1]=aa
argv[2]=bbb
sh: 1: pause: not found
CLC@Embed_Learn:~$
6、execlp 函数的特别之处:
每次execl函数调用新的程序或者系统指令都需要当前目录可执行文件的绝对路径,否则出错;execlp 函数可以通过PATH环境变量搜寻可执行文件;也就是说不管要执行的程序在哪个目录都可以通过环境变量找到。
——————————————————
使用execl函数的程序:
——————————————————
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
if(execl("ps","ps",NULL) == -1){
printf("execl faill\n");
perror("why:");
}
printf("execl faill\n");
system("pause");
return 0;
}
不带"p"的execl族函数的结果:
CLC@Embed_Learn:~$ ./execl
execl faill
why:: No such file or directory
execl faill
sh: 1: pause: not found
——————————————————————
使用execlp函数的程序:
——————————————————————
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char **argv)
{
if(execlp("ps","ps",NULL) == -1){
printf("execl faill\n");
perror("why:");
}
printf("execl faill\n");
system("pause");
return 0;
}
带"p"的execlp族函数的结果:
CLC@Embed_Learn:~$ ./a.out
PID TTY TIME CMD
2870 pts/0 00:00:01 bash
8595 pts/0 00:00:00 ps
补充:
a、如何查看当前环境变量
CLC@Embed_Learn:~$ echo $PATH //可以查看当前环境变量
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin
b、如何配置当前环境变量
CLC@Embed_Learn:~$ pwd //查看当前目录
/home/CLC
CLC@Embed_Learn:~$
CLC@Embed_Learn:~$
CLC@Embed_Learn:~$ echo $PATH
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin
CLC@Embed_Learn:~$ export PATH=$PATH:/home/CLC //配置当前目录到环境变量中
CLC@Embed_Learn:~$
CLC@Embed_Learn:~$ echo $PATH
/usr/lib/lightdm/lightdm:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/opt/FriendlyARM/toolschain/4.5.1/bin:/home/CLC
CLC@Embed_Learn:~$