您的位置:首页 > 运维架构 > Linux

Linux-程序替换

2018-03-22 16:23 134 查看

替换原理

用fork创建子进程,往往子进程要和父进程执行相同的程序,虽然也有可能时执行不同的代码分支,但是父子进程执行的都是同一程序。原因fork函数创建子进程,代码共享,数据写时拷贝。

那么假想,能不能让fork创建出来的子进程去执行另外一个程序呢。

答案是可以的。

当子进程去调用一种exec(系统调用)函数,就可以去执行另外一个程序。当进程调用exec函数时,该进程的代码与数据完全被新的程序的代码与数据所替换,从新程序的代码开始执行,所以说:调用exec并不创建新进程,所以调用exec函数前后进程pid并不会更改。

认识exec函数

exec系列函数共有六种,统称exec函数:



这些函数乍看起来很复杂,命名又多有不明白什么意思,只要了解了每个命名的含义就很好记了。

l:表示list,表示参数采用列表

v:表示vect,参数用数组

l与v不共存,因为他们都表示参数采用那种方式

p:表示path,由p自动搜索环境变量PATH

e:表示env,表示自己维护环境变量

事实上,只有execve是真正的系统调用,其他五个函数最终都调用了execve,所以在man查看时,它在man手册的第二章,其他函数则在man函数的第三章。

注意返回值:

- 这些函数如果调用成功则加载新的程序从启动代码开始执行,不再执行。

- 如果调用出错就返回-1

- 所以exec函数只有出错的返回值而没有成功的返回值。

举个例子:

int main()
{
char* const argv[]={"ls","-l","-a",NULL};
char* const envp[]={"PATH=/bin:/usr/bin","TERM=xterm",NULL};

execl("/bin/ls","ls","-l","-a",NULL);
execl("/bin/ls","ls","-l","-a",NULL);
execlp("ls","ls","-l","-a","NULL");//带p可以使用环境变量,无需全写路径
execle("ls","ls","-l","-a",NULL,envp);//带e的需要自己组装环境变量
execv("/bin/ls",argv);
execvp("ls",argv);
exit(0);
}




执行结果都相同,全部经过测试,证明exec函数是可以使用来进行程序替换的。

myshell

通过这种机制,我们可以实现一个自己的myshell,实现基本的一些功能。

暂不支持管道等功能。

先来看实现的结果:



代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <ctype.h>
char* argv[8];
int argc=0;
void do_prase(char* buf)
{
int i=0;
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_excute()
{
pid_t pid=fork();
if(pid==-1)
{
perror("fork");
exit(EXIT_FAILURE);
return;
}
else if(pid==0)
{
execvp(argv[0],argv);
perror("execvp");
exit(EXIT_FAILURE);
}
else
{
int st;
while(wait(&st)!=pid)
;
}
}

int main()
{
char buf[64]={};
while(1)
{
printf("[admin@myshell ~]$");
scanf("%[^\n]%*c",buf);
do_prase(buf);
do_excute();
}
return 0;
}


原理:首先需要获取命令行参数,然后对命令行进行分析,在创建子进程,让子进程去执行我们输入到命令行参数中的命令,用的当然是程序替换。然后让父进程等待子进程退出。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: