天天看點

【程序管理】程序三部曲:建立,執行與消亡(綜述)

在linux系統中,第一個程序是系統固有的,是由核心的設計者安排好的;一個新的程序一定要由一個已存在的程序複制出來,而不是創造出來的;其實linux系統并不提供直接建立程序的方法;linux将程序的建立與目标程式的執行分成兩步;

(1)從一個已存在的父程序像細胞分裂一樣地複制出一個子程序;實際複制出來的子程序有自己的task_struct和系統空間堆棧,但是與父程序共享其他資源;例如,要是父程序打開了5個檔案,那麼子程序也打開了這5個檔案,而且這些檔案的讀寫位置處于相同的位置;fork()是全部複制,父程序的所有資源全部通過資料結構複制給子程序,但程序号不一樣和clone()則帶有參數的選擇性的複制,可複制出一個線程,其他資源通過指針與父親來共享;vfork()是除了task_struct和系統空間堆棧外的資源通過指針全部複制,是以複制出來的是個線程,效率很高;

(2)然後就是目标程式的執行,建立一個程序是為有不同的目标程式要讓新的程式去執行,但複制完以後,子程序就要與父程序分道揚镳了,用execve(),讓一個程序執行以檔案形式存在的可執行程式映像了;

注:複制時隻複制程序基本資源的複制,如task_struct,系統空間堆棧,頁面表等,不包括父程序的代碼和全局變量,這些通過隻讀方式的共享,在需要寫的時候,通過copy_on_write()為所涉及的頁面建立一個新的副本;主要原因是通過複制下來的資源通常對子程序很有用,比如伺服器中的server端,還有pipe的通信;

建立了子程序以後,第一異步方式,父程序可以繼續走自己的路,與子程序分道揚镳,但是如果子程序先行exit(),那麼将要向父程序發一個信号;第二同步方式,父程序也可以選擇睡眠,等子程序exit()以後再去世,然後父程序再繼續執行,可使用wait3()某個特定的子程序,wait4()所有子程序;第三,自己exit()(是每一個可執行程式映像所必有的,是以在子程序中執行完後,不會傳回);

Linux核心中确實有一個建立核心線程的函數,kernel_thread(),供核心線程調用,它是對clone()的包裝,并不執行execve(),而是執行核心中某一個函數,會傳回是以要執行一個exit()系統調用;