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>





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章