淺析shell的工作原理
阿新 • • 發佈:2018-12-29
- 本章我們的內容將會介紹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對於命令的分析過程如下:
- 首先,檢查使用者輸入的命令是否是內部命令,如果不是在檢查是否是一個應用程式;
- shell在搜尋路徑或者環境變數中尋找這些應用程式;
- 如果鍵入命令不是一個內部命令並且沒有在搜尋路徑中查詢到可執行檔案,那麼將會顯示一條錯誤資訊;
- 如果能夠成功找到可執行檔案,那麼該內部命令或者應用程式將會被分解為系統呼叫傳給Linux核心,然後核心在完成相應的工作;
編寫一個簡單的shell
/*************************************************************************
> File Name: test.c
> Author: LZH
> Mail: www.597995302@qq.com
> Created Time: 2017 年02月13日 星期一 06時28分23秒
************************************************************************/
#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;
}
測試結果如下: