系统编程-exec函数族的使用
fork
创建子进程后执行的是和父进程相同的程序(但有可能执行不同的代码分支),子进程往往要调用一种exec
函数以执行另一个程序。当进程调用一种exec
函数时,该进程的用户控件代码和数据完全被新程序替换,从新程序的启动例程开始执行。执行exec
并不创建新进程,所以调用exec前后该进程的id并未改变。
将当前进程的.tex
t、.data
替换为所要加载的程序的.text
、.data
,然后让进程从新的.text
第一条指令开始执行,但进程ID
不变,换核不换壳。
//该函数通常用来调用用户自定义的可执行程序
int execl(const char *path, const char *arg, ...);
//该函数通常用来调用系统程序。如:ls、date、cp、cat等命令。
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[]);
“l”表示参数以列表的形式表示;
“v”表示参数以数组的形式表示;
“p”表示在PATH中搜索执行文件;
有“p”可以省去绝对路径
“e”表示可附加环境参数。
注意的地方有:
1、参数以NULL
或者0
结尾;
2、exec函数族执行成功后不会返回,执行失败会返回 -1
,错误代码存放在errno
中
3、可能的几种错误有,找不到文件或路径,errno
为ENOENT
;数组argv
或envp
没有以NULL
或者0
结尾,errno
为EFAULT
;没有对执行文件的执行权限,errno
为EACCESS
;
测试代码:
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
int main(int argc,char** argv){
char* envp[] = {"PATH=/usr/bin","USER=admin",0};
char* argv_execv[] = {"echo","exec on execv",0};
char* argv_execvp[] = {"echo","exec on execvp",0};
char* argv_execve[] = {"echo","exec on execve",0};
if(fork() == 0){
if(execl("/bin/echo","echo","execut by execl",NULL) < 0){
perror("error on execl");
}
}
if(fork() == 0){
if(execlp("echo","echo","exec by execlp",NULL) < 0 )
perror("error execlp");
}
if(fork() == 0){
if(execle("/bin/echo","echo","execut by execle",NULL,envp) < 0){
perror("error on execle");
}
}
if(fork() == 0){
if(execv("/bin/echo",argv_execv) < 0){
perror("error on execv");
}
}
if(fork() == 0){
if(execvp("echo",argv_execvp) < 0)
{
perror("error on execvp");
}
}
if(fork() == 0){
if(execve("/bin/echo",argv_execve,envp) < 0)
{
perror("error on execve");
}
}
return 0;
}
运行结果: