c語言實現shell


shell的編寫

命令行傳參數

每個C語言程序都必須有一個稱為main()的函數,作為程序啟動的起點。當執行程序時,命令行參數(command-line argument)(由shell逐一解析)通過兩個入參提供給main()函數。第一個參數int argc,表示命令行參數的個數。第二個參數char *argv[],是一個指向命令行參數的指針數組,每一參數又都是以空字符(null) 結尾的字符串。第一個字符串,亦即argv[0]指向的,(通常)是該程序的名稱。argv中的指針列表以NULL指針結尾(即argv[argc]為NULL)。

創建子進程

  1. 在父程序中,fork返回子進程的PID,在子進程中,fork返回0;

Linux中wait用法:

系統中的僵屍進程都要由wait系統調用來回收。
函數原型:

#include<sys/types.h>
#include<sys/wait.h>
pid_t wait(int *status);

進程一旦調用了wait就立即阻塞自己,由wait自動分析是否當前進程的某個子進程已經退出,如果讓它找到了這樣一個已經變成僵屍的子進程,wait就會收集這個子進程的信息,並把它徹底銷毀后返回;如果沒有找到這樣一個子進程,wait就會一直阻塞在這里,直到有一個出現為止。
參數status用來保存被收集進程退出時的一些狀態,它是一個指向int類型的指針。但如果我們對這個子進程是如何死掉毫不在意,只想把這個僵屍進程消滅掉,,我們就可以設定這個參數為NULL,就像下面這樣:

pid = wait(NULL);

如果成功,wait會返回被收集的子進程的進程ID,如果調用進程沒有子進程,調用就會失敗,此時wait返回-1,同時errno被置為ECHILD。

疑惑1:為什么要創建子進程?什么時候創建子進程?如果不創建子進程會怎樣?

創建子進程才能多道程序並發執行。進程是資源分配的單位,是運行的程序。既然是運行的程序,一個進程自然只能代表一個程序,多道程序設計自然而然就有了多進程的概念。比如word算是個典型的多進程程序,有個進程接受你的鍵盤輸入,有拼寫檢查進程,有顯示進程等等。大多數都用到網絡上了,比如服務器。一台服務器要在“同一時間”處理來自很多客戶端的請求,這就必須使用多進程。再比如上課所用的execve,如果創建子進程,再執行一次后就會退出程序,與我們所希望的結果不符。

疑惑2:為什么要防止出現僵死進程

首先我們要理解什么是僵死進程,僵死進程
一個僵死進程是在父進程退出之前就終止的子進程(子進程在父進程之前終止,此時因為父進程還沒有退出,所以系統會保留子進程的pid,退出
狀態,返回給父進程有wait函數,如果父進程沒有wait函數,系統就會一直保持子進程的PID等信息,直到父進程退出)之所以被稱為僵死進程是因為他雖然死掉了,但依然在進程表中存在。
子進程退出后分配給他的內存和其他資源都被釋放,但是子進程還在內核進程表保留一條,內核在父進程回收子進程的退出狀態前一直保留它。
有一個兩個僵死進程不算什么問題,但一旦一個程序頻繁執行fork或者execv卻又不能手機退出狀態,那么最終將會填滿進程表(內核進程表是有上限的),這會影響性能,可能導致系統重啟。所以我們要在父進程調用wait或者waitpid函數等待進程終止。

偽代碼:

while(1){

    輸入命令;
    解析命令;
    創建子進程;
    執行程序;
    wait();
}

實驗結果:

實驗代碼


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM