1. 程式人生 > >Linux下模擬實現一個微型shell

Linux下模擬實現一個微型shell

首先我們先看一下shell的執行過程:

     

        shell從使用者讀入字串"ls",並建立一個新的程序,在那個程序中執行ls程式並等待那個程序結束。然後shell讀取新的一行輸入,建立一個新的程序,在這個程序中執行程式並等待這個程序結束。

所以我們要寫一個微型shell,需要迴圈以下過程:

  1.  獲取終端輸入。
  2.  解析輸入(按空格解析到一個一個的命令引數)。
  3. 建立一個子程序,在子程序中進行程式替換,讓子程序執行命令。
  4. 等待子程序執行完畢,收屍,獲取退出狀態碼。

根據這個思路和我們之前學習到的知識,就可以自己實現一個微型shell了。

來看程式碼(使用Linux作業系統實現):

#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>

int argc;
char *argv[32];
int param_parse(char *buff)
{
	// ls -l
	if (buff == NULL)
		return -1;
	char *ptr = buff;
	char *tmp = ptr;
	argc = 0;
	while ((*ptr) != '\0')
	{
		//當遇到空格,並且下一個位置不是空格的時候,將空格位置置位為'\0'
		//然後用argv[argc]來儲存這個字串的位置
		if ((*ptr) == ' ' && *(ptr + 1) != ' ')
		{
			*ptr = '\0';
			argv[argc] = tmp;
			tmp = ptr + 1;
			argc++;
		}
		ptr++;
	}
	argv[argc++] = tmp;
	argv[argc] = NULL;
	return 0;
}

int exec_cmd()
{
	int pid = 0;
	pid = fork();
	if (pid < 0)
		return -1;
	else if (pid == 0)
	{
		execvp(argv[0], argv);
		exit(0);
	}
	//父程序在這裡必須等待子程序退出,來看看子程序為什麼退出了,是不是出現了什麼錯誤。
	//通過獲取狀態碼,並且轉換一下退出碼所對應的錯誤資訊進行列印。
	int statu;
	wait(&statu);
	//判斷子程序是否程式碼執行完畢退出
	if (WIFEXITED(statu))
	{
		//獲取到子程序的退出碼,轉換為文字資訊列印。
		printf("%s\n", strerror(WEXITSTATUS(statu)));
	}
	return 0;
}

int main()
{
	while (1)
	{
		printf("mashell> ");
		char buff[1024] = { 0 };
		// %[^\n]  獲取資料直到遇到\n為止
		// %*c     清空緩衝區,資料都不要了
		scanf("%[^\n]%*c", buff);
		printf("%s\n", buff);
		param_parse(buff);
		exec_cmd;
	}
	return 0;
}

 測試結果: