shell具体执行过程及自主实现shell解释器

在编写shell解释器之前,先来分析几个知识点:

1shell执行命令时步骤:(如下图)


2shell执行脚本时的步骤:(如下图)


      在这里,有一个知识点必须知道,那就是shell命令下的内建命令,(内建命令在命令行上一般是直接由bash直接执行后退出的,这是因为磁盘上没有对应的可执行程序供系统执行程序替换,所以自然而然也不会创建子进程喽;而如果在shell脚本下的话,执行cd  ..并不能达到我们的要求,因为它在shell脚本下是由fork出的子进程去执行,与父进程bash无关,我们常使用的cd .. 命令就是其中的一个典型代表。下面以一个具体例子来说明:

先来编写一个简单的shell脚本程序,如下:

#! /bin/bash
ls
cd ..
pwd

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">当然,此时可以猜测一下执行这个脚本的结果,是不是显示出上一级目录下的所有文件及目录呢?下面就来看一看真正的执行结果:(如下图)</span>


如此,我们就可得到一个结论:当内置命令直接在命令行上执行时,bash就化身为进程在前台执行后直接返回,所以在这个例子中它就返回到了上层目录;而当内置命令在shell脚本中执行时,bash fork出的子进程就去执行了内置命令,与bash进程执行无关,所以出现了上图还在本级目录下的结果。

好啦!以上就是bash的一些比较重要的点的分析了!下面就来编写一个自主的shell

<span style="font-size:18px;">#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
void Swap(char **beginn,char **endd)
{
	char *tmp=*beginn;
	*beginn=*endd;
	*endd=tmp;
}
int main()
{
	while(1)
	{
	printf("[myshell@localhost shell]$");
	fflush(stdout);
	char buf[1024];
	memset(buf,'\0',sizeof(buf));
	ssize_t _size=read(0,buf,sizeof(buf)-1);//get value from inout
	buf[_size-1]='\0';
//	printf("%s\n",buf);
	char *my_argv[64];
	int end=strlen(buf)-1;
	int begin=0;
	int index=0;
	while(end>=0)
	{
		//end-->begin
		if(isspace(buf[end-1]))//the head of first request  is empty
		{
			my_argv[index++]=&buf[end];
		}
		if(isspace(buf[end]))//last is empty
		{
			buf[end]='\0';</span>
<span style="font-size:18px;">		}
		--end;
	}
	my_argv[index++]=buf;
	my_argv[index]=NULL;
	int start=0;
    end=index-1;
	//swap my_argv[start] my_argv[end]
	while(start<end)
	{
		Swap(&my_argv[start],&my_argv[end]);
		++start;
		--end;
	}
	index=0;
	for(;my_argv[index]!=NULL;index++)
	{
      printf("%s\n",my_argv[index]);
	}
	if(strcmp(my_argv[0],"cd")==0)//judge is build-in command?
	{
       chdir(my_argv[1]);//menu is change 
       continue;
	}
	//is not build-in command,fork process 
	pid_t id=fork();
	if(id<0)
	{
		perror("fork");
		exit(1);
	}
	else if(id==0)
	{
		execvp(my_argv[0],my_argv);
		exit(1);
	}
	else 
	{
		pid_t ret=waitpid(id,NULL,0);
		if(ret==id)
		{
           // printf("wait successful\n");
		}
	}
	}
	return 0;
}</span>





  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值