进程的替换
exec 函数族, 是由六个 exec 函数组成的
exec 函数族提供: 六种在进程中启动另一个程序的方法
exec 函数族可根据 指定的文件名或目录名找到 可执行文件
调用 exec 函数的进程并不创建新的进程, 故调用 exec 前后, 进程的进程号并不会改变, 其执行的程序完全由新的程序替换, 而新程序则从其 main 函数开始执行
exec 函数族取代调用进程的数据段、 代码段和堆栈段
exec 函数族
#include <unistd.h>
int execl(const char *pathname,
const char *arg0,...
NULL);
int execlp(const char *filename,
const char *arg0,...
NULL);
int execle(const char *pathname,
const char *arg0,..
NULL,
char *const envp[]);
int execv(const char *pathname,
char *const argv[]);
int execve(const char *pathname,
char *const argv[],
char *const envp[])
六个 exec 函数中只有 execve 是真正意义的系统调用(内核提供的接口), 其它函数都是在此基础上经过封装的库函数
l(list):
参数地址列表, 以空指针结尾。
参数地址列表:
char *arg0, char *arg1, ..., char *argn, NULL
v(vector):
存有各参数地址的指针数组的地址
使用时,先构造一个指针数组, 指针数组存各参数的地址, 然后将该指针数组地址作为函数的参数
p(path):
按 PATH 环境变量指定的目录搜索可执行文件
以 p 结尾的 exec 函数取文件名做为参数
当指定 filename 作为参数时, 若 filename 中包含/, 则将其视为路径名, 并直接到指定的路径中执行程序
e(environment):
存有环境变量字符串地址的指针数组的地址
execle 和 execve 改变的是 exec 启动的程序的环境变量( 新的环境变量完全由 environment 指定), 其他四个函数启动的程序则使用默认系统环境变量
注意:
exec 函数族与一般的函数不同, exec 函数族中的函数执行成功后不会返回
只有调用失败了, 它们才会返回- 1
失败后从原程序的调用点接着往下执行
在平时的编程中, 如果用到了 exec 函数族, 一定要记得加错误判断语句
getenv函数:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
printf("USER = %s\n",getenv("USER"));
printf("GONGSI = %s\n",getenv("GONGSI"));
return 0;
}
打印:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
execl("/bin/ls","ls","-a","-l","-h",NULL);
perror("execl");
return 0;
}
打印:
execlp函数:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
execlp("ls","ls","-a","-l","-h",NULL);
perror("execlp");
return 0;
}
打印:
execv函数
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char *arg[] = {"ls", "-a", "-l", "-h", NULL};
execv("/bin/ls",arg);
perror("execv");
return 0;
}
打印:
execvp函数:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char *arg[] = {"ls","-a","-l","-h",NULL};
execvp("ls",arg);
perror("execvp");
return 0;
}
打印:
execve函数:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
char *arg[]={"test", NULL};
char *env[]={"USER=ME", "GONGSI=AIPU", NULL};
execve("./test", arg, env);
perror("execve");
return 0;
}
一个进程调用 exec 后, 除了进程 ID, 进程还保留了下列特征不变:
父进程号 , 进程组号 , 控制终端 , 根目录 , 当前工作目录 , 进程信号屏蔽集 , 未处理信号