2013年4月19日 星期五

Shell 內建命令 (Shell Built-in Command)



Shell Built-in Command 是指與 shell code 寫在一起編譯成,屬於 shell 這個 program 本身功能的指令,在Windows中稱為 internal command,例如:cd, exit, umask, alias 等等,這種內建在 shell 程式碼內的功能無法在 shell 中使用 execv() 去呼叫外部程式的方式執行

<Shell.c>
int main()
{
    ...
     if( strcmp(cmd, "cd") == 0)
            cd(pathname);
    ...
}



void cd(char *pathname)
{ ... chdir(... pathname ...) ... }


這種命令的執行速度會比 external program 快,因為省去了 program loading 這段 overhead,但是因為這些功能的程式碼是寫在 shell 中,所以如果修改或更新了任何功能的程式碼,就必須將整個 shell program 重新 compile 一次

那麼是什麼樣的命令適合實作成 builtin 呢?

舉個例子來說明,像是 cd 這個命令,用途是在不同的目錄間移動,實作方式大致上是使用 chdir() 這個函式,不過我們討論的不是實作的方法,而是這個函式的運作方式,對大部分的作業系統而言,當一個 Process 開啟一個檔案(目錄也是一個檔案)時,OS會為該 Process 建立他自己的 Process Table,其中就包含了現行工作目錄的資訊,而 chdir() 就是用來讓呼叫它的 Process 在執行期間移動自己的現行目錄

我們知道,cd 這個命令主要是用來改變目前的工作目錄,而這個工作目錄是屬於目前這個 Process 自己知道的資訊,其他 Process 不會知道也不需要知道

當一個 Process 呼叫一個 function ,這個 function 基本上只會對呼叫它的 Process 有作用

如果我們把 cd 實作成一個外部程式,也就是說,寫一個命名為 cd.c 的 program 並且編譯後程式名稱為 cd,當然,cd.c 中呼叫了 chdir() 這個函式,那麼當 shell process 使用 execv() 呼叫了這個外部程式後,這個外部程式便開始執行,注意!因為 cd 也是一個程式,根據對 Process 的定義,cd 被執行後,也會是一個 Process,也就是說,現在同時有兩個不同的 Process 在系統中執行,又據前一段所言,因為呼叫 chdir() 的 Process 是 cd,所以 chdir() 只會對 cd process 有作用,也就是會切換 cd process 的工作目錄,如此一來,shell 的工作目錄還是維持不變

因此如果我們希望使用者在 shell 輸入 cd 以後,可以改變 shell 的工作目錄,則必須在 shell process 中呼叫 chdir() ,這就是之所以要將 cd 實作成內建命令的原因

像是 umask(改變建檔時檔案權限遮罩)、exit (呼叫 exit() 終止 shell 這個 Process)、alias...都是差不多的原因,因為建檔時對檔案的權限設定使用的遮罩是個別 process 的東西,因此需要在各Process 內使用;因為要結束 shell 自己這個 process,是呼叫 exit(),如果採用呼叫外部程式,那只會結束那個外部的程式 (那個程式被執行起來後用來結束自己 ....... ~"~? )

總結一下,由這些例子可知,要實作為 built-in 的基本概念就是『這個命令只會對使用它的 process 本身有影響』,像是 ls,純粹只是對一個目錄進行開啟、讀取與列印內容,對使用這個命令的 Process 並沒有影響;像是 mv,也只是對一個檔案進行移動,對 Process 的參照不會有影響,所以這些命令沒有必要做成內建命令








沒有留言:

張貼留言