系统调用exe函数族对当前进程进行替换,替换着为一个指定程序,其参数包括文件名filename,参数列表argv,以及环境变量envp
整个函数家族如下:
#include <unistd.h>
extern char **environ;
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 execve(const char *path, char *const argv[], char *const envp[]);
在名字中缺“e”的是从当前进程中拷贝环境,有字母“p”的是可以在当前路径中查找文件,而其他函数必须在指定路径中找,这里要注意执行路径,有安全隐患,慎用。
练习1:用系统命令替换
- /* exec.c */
- #include <unistd.h>
- main()
- {
- /*定义参数*/
- char *envp[]={"PATH=/tmp", "USER=lei", "STATUS=testing",NULL};
- char *argv_execv[]={"echo", "excuted by execv", NULL};
- char *argv_execvp[]={"echo", "executed by execvp", NULL};
- char *argv_execve[]={"env", NULL};
- /*全部在子进程运行*/
- if(fork()==0)
- if(execl("/bin/echo", "echo", "executed by execl", NULL)<0) //调用echo命令,参数:executed by execl
- perror("Err on execl");
- if(fork()==0)
- if(execlp("echo", "echo", "executed by execlp", NULL)<0)
- //调用echo命令,参数:executed by execlp
- perror("Err on execlp");
- if(fork()==0)
- if(execle("/usr/bin/env", "env", NULL, envp)<0) //env命令,打印当前环境envp
- perror("Err on execle");
- if(fork()==0)
- if(execv("/bin/echo", argv_execv)<0) //echo命令,参数argv_execv指向的内容
- perror("Err on execv");
- if(fork()==0)
- if(execvp("echo", argv_execvp)<0) //echo命令,参数argv_execvp指向的内容
- perror("Err on execvp");
- if(fork()==0)
- if(execve("/usr/bin/env", argv_execve, envp)<0)
- //env命令
- perror("Err on execve");
- }
程序里调用了2个Linux常用的系统命令,echo和env。echo会把后面跟的命令行参数原封不动的打印出来,env用来列出所有环境变量。
编译,测试:
$ ./exec
executed by execl
executed by execlp
PATH=/tmp
USER=lei
STATUS=testing
executed by execlp
excuted by execv
executed by execvp
PATH=/tmp
USER=lei
STATUS=testing
练习2:子进程执行用户自己编写的程序
先写父进程的程序:
- /*parent.c*/
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- int main(void)
- {
- pid_t pid;
- const char *usr_envp[] = {"MYDEFINE=unknown","PATH=/home",NULL};//路径
- printf("Begin Fork()/n");
- pid = fork();
- switch(pid)
- {
- case -1:
- perror("fork failed!/n");
- break;
- case 0:
- /*准备执行子进程的程序*/
- if(execle("/home/child","myarg1","myarg2",(char *)0,usr_envp)) //路径/home/child,参数...
- perror("execle failed!/n");
- break;
- default:
- break;
- }
- //等待子进程退出
- if(waitpid(pid,NULL,0)<0)
- perror("waitpid failed!/n");
- printf("parent excting!");
- return 0;
- }
然后我们编写子进程要执行的程序:
- /*child.c*/
- #include <sys/types.h>
- #include <unistd.h>
- #include <stdio.h>
- int main(int argc,char *argv[])
- {
- int i;
- char **pStr;
- extern char **environ;
- printf("child starting!/n");
- //打印出参数名
- for(i = 0;i < argc;i++)
- {
- printf("argv[%d]:%s/n",i,argv[i]);
- }
- //打印出路径名
- for(pStr = environ; *pStr != 0;pStr++)
- {
- printf("%s/n",i,*pStr);
- }
- printf("child exiting!/n");
- return 0;
- }
然后编译,执行parent
$ ./parent
Begin Fork()
child starting!
argv[0]:myargv1
argv[1]:myargv2
child exiting!
parent excting!