Linux內核 ——進程管理之進程誕生(基於版本4.x)


《奔跑吧linux內核》3.1筆記,不足之處還望大家批評指正

進程是Linux內核最基本的抽象之一,它是處於執行期的程序。它不僅局限於一段可執行代碼(代碼段),還包括進程需要的其他資源。在Linux內核中常被稱作任務。

線程被稱為輕量級進程,是操作系統調度的最小單元,通常一個進程可以擁有多個線程。

進程和線程的區別在於進程擁有獨立的資源空間,而線程則共享進程的資源空間。

問題一:在內核中如何獲取當前進程的task_struct數據結構?

  內核有一個常用的常量current用於獲取當前進程task_struct數據結構,它利用了內核棧的特性。首先通過sp寄存器獲取當前內核棧的地址,對齊后獲取struct thread_info數據結構指針,最后通過thread_info->task成員獲取task_struct數據結構。圖1為linux內核棧的結構圖。

圖1 內核棧

 

問題二:下面程序會打印幾個“_”?

int main(void){

  int i;

  for(i=0; i<2; i++){

    fork();

    printf("_\n");}

  wait(NULL);wait(NULL);

  return 0;}

   答案是6個“_”,具體思路如圖2所示。(i=0,調用一次fork后,父進程a創建子進程b,此后a和b進行打印,打印兩個“_”;后i=1,a和b均調用fork,a創建子進程a_1,b創建子進程b_1,4個進程執行打印操作,打印出四個“_”;i=2,返回)

圖2 fork解題思路

 

問題三:用戶空間進程的頁表是什么時候分配的,其中一級頁表什么時候分配?二級頁表呢?

   (此問有點疑問,暫且認為一級頁表為頁目錄項(pgd),二級頁表為也表項(pte))

  對於內核來說,進程的“鼻祖”是idle進程,稱為swapper進程;對於用戶空間來說,進程“鼻祖”是init進程,所有用戶空間進程都由init進程創建或派生。

  在mm_init()函數中,首先給新進程的mm_struct數據結構進行初始化,然后對mm_users,mm_count進行初始化,設置進程空間地址讀寫信號量,設置保護進程頁表的spinlock鎖,最后調用pgd_alloc()函數進行pgd頁表的分配工作。在pgd_alloc()函數中,調用pte_alloc_map()函數進行第0,第1個頁表的分配,此后在dup_mmap()函數中將父進程所有的VMA對應的pte頁表項復制到子進程對應的pte頁表項中。

問題四:請簡述fork,vfork和clone之間的區別?

   fork,vfork,clone的實現都是通過調用do_fork()函數實現的,只是函數調用不一樣。

  fork函數實現:do_fork(SIGCHLD,0,0,NULL,NULL);只使用SIGCHLD標志位,在子進程終止后發送SIGCHLD信號通知父進程。fork是重量級調用,為子進程建立了一個基於父進程的完整副本,然后子進程基於此運行。為了減少工作量采用寫時復制技術(COW),子進程只復制父進程的頁表,不復制頁面內容。當子進程需要寫入新內容時,才觸發寫時復制機制,為子進程創建一個副本。

  vfork函數實現:do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,0,0,NULL,NULL);它比fork多了兩個標志位,分別為CLONE_VFORK和CLONE_VM。CLONE_VFORK表示父進程會被掛起,直至子進程釋放虛擬內存資源。CLONE_VM表示父子進程運行在相同的內存空間中。

  clone函數實現:do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);clone用於創建線程,並且參數通過寄存器從用戶空間傳遞下來,通常會指定新的棧地址(newsp)。

 


免責聲明!

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



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