資源描述:
《linux 學習筆記 - 進程》由會員上傳分享,免費在線閱讀,更多相關內(nèi)容在行業(yè)資料-天天文庫。
1、Linux進程1基本內(nèi)容進程,作為Linux里面的兩大基本抽象之一,籠統(tǒng)來說就是執(zhí)行中的程序。這樣一個概念涵蓋的內(nèi)容很豐富:匯編代碼、數(shù)據(jù)、狀態(tài)、各種資源(包括文件、信號、內(nèi)存等等)。本文檔未包含進程間通信、同步等內(nèi)容。1.1標識一個進程每一個進程,在內(nèi)核中,都對應了一個task_struct結(jié)構(gòu)體,也稱為進程描述符,其中包含了描述一個進程的所有信息(約1.7K字節(jié))。在內(nèi)核中,所有的的task_struct都被組織在任務隊列這樣一個雙向鏈表中,如下圖:操作系統(tǒng)通過進程IDpid來區(qū)分不同的進程描述符,該變量為了與老版本的Linux兼容,其最
2、大值的默認值被默認設置為32768。這樣的取值對于一般的個人機是足夠使用了,但是有些大型的服務器可能會需要更多的進程。這個最大值可以進行設置,如果不考慮兼容性,可以設置成超過32768。既然task_struct記錄了所有進程相關的描述信息,不難想象內(nèi)核大部分對進程的操作都是通過該結(jié)構(gòu)進行,那么高效的訪問task_struct就十分重要了。X86體系中,內(nèi)核訪問task_struct的示意圖如下:2010-06-27Page11,Total11第11頁,共11頁在進程的內(nèi)核棧的最底端有一個thread_info結(jié)構(gòu),其保存了task_stru
3、ct的地址。宏current_thread_info()會取到本進程的thread_info,則current_thread_info()->task_struct即可。current_thread_info的實現(xiàn)值得注意:將棧指針SP的后12/13位與0相與。兩種取值分別對應了4k/8k的內(nèi)核棧。1.1進程狀態(tài)Linux進程有5種狀態(tài):lTASK_RUNNING:運行狀態(tài)–正在執(zhí)行或者在等待執(zhí)行的任務隊列中l(wèi)TASK_INTERRUPTIBLE:進程睡眠(或者說阻塞)lTASK_UNINTERRUPTIBLE:不可中斷–等待時不可被信號喚醒
4、這類進程就是無法被kill命令殺死的進程了,也因此較上一種使用的較少lTASK_ZOMBIE:僵尸–進程已經(jīng)結(jié)束,但為了父進程能夠獲得相關信息,內(nèi)核還保留了該進程的一些相關信息,–直到父進程調(diào)用wait4()lTASK_STOPPED/TASK_TRACED:暫停執(zhí)行、調(diào)試狀態(tài)–一般都是通過特定的信號來實現(xiàn)本狀態(tài)與運行狀態(tài)的切換下面是FSM:2010-06-27Page11,Total11第11頁,共11頁1.1進程上下文當一個進程執(zhí)行了系統(tǒng)調(diào)用,或者發(fā)生了某個異常,此時它將陷入內(nèi)核空間對內(nèi)核的訪問,必須通過內(nèi)核提供的系統(tǒng)調(diào)用,或者異常處理程
5、序,都有特定的接口,我們稱內(nèi)核將“代表進程執(zhí)行”,并且處于進程上下文中。進程上下文中,current宏是有效的。當調(diào)用結(jié)束或者異常處理結(jié)束,程序恢復在用戶空間的繼續(xù)執(zhí)行。中斷有專門的中斷上下文。1.2進程的創(chuàng)建1.2.1進程體系除了init進程之外,其他的進程都有其父進程(ppid)。每一個進程都有其所屬的用戶以及進程組,這是為了實現(xiàn)訪問控制。另外注意的是,在Linux中,創(chuàng)建進程和加載可執(zhí)行文件是兩個步驟,分別通過fork系列函數(shù)已經(jīng)exec系列函數(shù)調(diào)用進行。1.2.2forkfork用來創(chuàng)建子進程,子進程與父進程在以下幾點上是不同的:lp
6、id/ppidl各類資源統(tǒng)計信息清零2010-06-27Page11,Total11第11頁,共11頁l所有掛起的信號被清除,子進程不進行繼承l(wèi)所有文件鎖不會被繼承Linux通過clone()系統(tǒng)調(diào)用來實現(xiàn)fork,這個系統(tǒng)調(diào)用的命名很貼切,這么說的原因在下面會看到。fork調(diào)用有2個返回值:父/子進程的pid。內(nèi)核通常傾向于先返回子進程的pid。子進程在被創(chuàng)建初始,和父進程平分剩余的時間片。1.1.1exec當子進程創(chuàng)建成功并且被調(diào)度執(zhí)行時,一般都會調(diào)用exec系列函數(shù)將目標可執(zhí)行文件加載到內(nèi)存中。通常,exec系列函數(shù)調(diào)用都不會返回,成功
7、的調(diào)用回跳到新的程序入口點進行執(zhí)行,而之前運行的代碼是不會存在于新的地址空間中的。exec調(diào)用改變了以下的進程信息:l掛起的信號丟失,鎖定的內(nèi)存丟失,與進程內(nèi)存相關的信息丟失,包括文件映射l多數(shù)進程統(tǒng)計信息清零,多數(shù)線程屬性還原到默認值l信號處理函數(shù)還原到默認的函數(shù)l最重要的是,改變了地址空間和進程的映像繼承了的東西則有文件描述符集。1.1.2寫時拷貝前面提到clone這個系統(tǒng)調(diào)用名稱很貼切,原因就在于,Linux內(nèi)核通過寫時拷貝技術來進行子進程的創(chuàng)建。為什么要使用寫時拷貝?早期的內(nèi)核其實是這么干的:調(diào)用fork時,內(nèi)核會把所有內(nèi)部數(shù)據(jù)復制一
8、份,復制進程的頁表項,把父進程地址空間中的內(nèi)容逐頁復制到子進程的地址空間中。對于內(nèi)核而言,主頁拷貝是效率十分低下,十分耗時的操作。寫時拷貝怎么實現(xiàn)?在創(chuàng)建進程時,并