淺析shell的工作原理

  • 本章我們的內容將會介紹Linux中的命令解釋器shell的工作原理
  • 我們還會編寫一個簡單的shell

什麼是shell?

Linux系統的shell相當於操作系統的“一層外殼”,它是命令語言解釋器,它爲用戶提供了使用操作系統的接口,它不屬於內核,而是在內核之外以用戶態方式運行。它的基本功能是解釋並執行用戶打入的各種命令,實現用戶與Linux內核的接口。
在啓動Linux系統後,內核會爲每個終端用戶建立一個進程去執行shell解釋程序,它的執行過程遵循以下步驟:

1.讀取用戶由鍵盤輸入的命令;
2.對命令進行分析,以命令名爲文件名,並將其他參數改造爲系統調用execve()參數處理所要求的格式;
3.終端進程(shell)調用fork()或者vfork()建立一個子進程;
4.子進程根據文件名(命令名)到目錄中查找有關文件,將他調入內存,並創建新的文本段,並根據寫時拷貝的方式創建相應的數據段、堆棧段;
5.當子進程完成處理或者出現異常後,通過exit()或_exit()函數向父進程報告;
6.終端進程調用wait函數來等待子進程完成,並對子進程進行回收;


shell對輸入的命令的分析

在Linux中,有一些命令,例如cd是包含在shell內部的命令,還有一些命令,例如cp、mv或rm是存在於文件系統中某個目錄下的單獨的程序。對於用戶而言,沒必要關心一個命令是在shell內部還是在shell外部。
shell對於命令的分析過程如下:

  1. 首先,檢查用戶輸入的命令是否是內部命令,如果不是在檢查是否是一個應用程序;
  2. shell在搜索路徑或者環境變量中尋找這些應用程序;
  3. 如果鍵入命令不是一個內部命令並且沒有在搜索路徑中查找到可執行文件,那麼將會顯示一條錯誤信息;
  4. 如果能夠成功找到可執行文件,那麼該內部命令或者應用程序將會被分解爲系統調用傳給Linux內核,然後內核在完成相應的工作;

編寫一個簡單的shell

/*************************************************************************
    > File Name: test.c
    > Author: LZH
    > Mail: www.597995302@qq.com 
    > Created Time: 20170213日 星期一 062823************************************************************************/

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>


int main()
{
    pid_t id=fork();
    printf("Load MyShell\n");
    char buf[1024];
    ssize_t Len;
    char* Argv[10];
    int i=0;
    if(id==0){
            while (1)
            {
                //child
                printf("[lzh@localhost MyShell]#");
                fflush(stdout);   //flush buf
                Len = read(0, buf, 1024);
                if (Len>0)
                {//read Success
                    buf[Len - 1] = '\0';
                    printf("Debug:%s\n", buf);
                    int count = 0;
                    char* Start;
                    for (Start = buf; *Start != '\0'; Start++)
                    {
                        Argv[count++] = Start;
                        while (*Start != ' '&&*Start != '\0')
                        {
                            Start++;
                        }
                        if (*Start == '\0')
                        {
                            break;
                        }
                        *Start = '\0';      //*Start==' ',replace 
                    }
                    printf("count:%d\n", count);
                    Argv[count] = NULL;
                    for (i = 0; Argv[i] != NULL; i++)
                    {
                        printf("%d,Debug:%s\n", i, Argv[i]);
                    }
                    execvp(Argv[0], Argv);
                    //  printf("Error\n");
                    //  exit(1);
                }
                else
                {//read error ,finish now cycle
                    perror("Read Error!\n");
                    continue;
                }
                printf("\n");
            }
    }
    else{
            //father
            sleep(1);
            printf("I am father,pid:%d,ppid:%d\n",getpid(),getppid());
            wait(NULL);
    }
    return 0;
}

測試結果如下:
這裏寫圖片描述


相關文章:

進程管理之程序替換:
http://blog.csdn.net/bit_clearoff/article/details/55051580

進程管理之創建進程、進程等待、終止進程:
http://blog.csdn.net/bit_clearoff/article/details/54603375

發佈了89 篇原創文章 · 獲贊 190 · 訪問量 21萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章