进程的程序替换
替换原理
我们在使用fork()函数的时候,会创建一个子进程,一般情况下,子进程会与父进程执行相同的代码,可以用if语句分支开父子进程执行的代码,而这时候可以调用exec函数进行替换,当我们调用exec函数的时候,该进程的代码和数据完全被一个新的程序所替代,从新程序的启动入口执行,但是并不会产生新的进程,所有调用exec之后,进程的id并不会改变。
替换函数
有六种exec开头的函数可进行程序替换,统称为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 execve(const char* path,char* const argv[],char* const envp[]);
调用以上函数如果成功那么直接进行新的程序,如果失败返回值为-1,所以exec类函数只有失败的返回值并没有成功的返回值。
命名理解
- l:表示参数采用列表
- v:参数用数组
- p:由p自动搜索环境变量PATH
- e:表示自己维护环境变量
调用举例
#include <unsitd.h>
int main()
{
char* const argv[] = {"ps","-ef",NULL};
char* const envp[] = {"PATH=/bin:/usr/bin","TERM=console",NULL};
execl("/bin/ps","ps","-ef",NULL);
//带p的,可以使用环境变量PATH,无需写全路径
execlp("ps","ps","-ef",NULL);
//带e的,需要自己组装环境变量
execle("ps","ps","-ef",NULL,envp);
execv("/bin/ps",argv);
//带p的,可以使用环境变量PATH,无需写全路径
execvp("ps",argv);
//带e的,需要自己组装环境变量
execve("/bin/ps",argv,envp);
}
实际上,只有execve是真正的系统调用,其他五个函数最终都是调用execve。
利用exec函数实现简易版的shell程序
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
char* argv[8];
int argc = 0;
void do_parse(char* buf)
{
int i;
int status = 0;
for(argc=i=0; buf[i]; i++)
{
if(!isspace(buf[i]) && status == 0)
{
argv[argc++] = buf+i;
status =1;
}
else if(isspace(buf[i]))
{
status = 0;
buf[i] = 0;
}
}
argv[argc] = NULL;
}
void do_execute()
{
pid_t pid = fork();
if(pid < 0)
{
perror("fork");
exit(1);
}
else if(pid == 0)
{
execvp(argv[0],argv);
perror("execvp");
}
else
{
int st;
while( wait(&st) != pid )
{
;
}
}
}
int main()
{
char buf[1024] = {};
while(1)
{
printf("myshell###");
scanf("%[^\n]%*c",buf);
do_parse(buf);
do_execute();
}
return 0;
}
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!