進程的描述和進程的創建
一,進程的描述
進程控制塊PCB——task_struct (進程描述符),為了管理進程,內核必須對每個進程進行清晰的描述,進程描述符提供了內核所需了解的進程信息。
struct task_struct數據結構很龐大,進程的標示pid。
Linux進程的狀態與操作系統原理中的描述的進程狀態有所不同,task_running代表就緒和運行兩種狀態,取決于它是否獲得CPU的控制權。
在這個龐大的數據結構里,所有進程鏈表struct list_head tasks,一個雙向鏈表。
程序創建的進程具有父子關系,在進程調度中會用到,進程描述符中會有幾個域用來表示這樣的關系。
Linux為每個進程分配一個8KB大小的內存區域,用于存放該進程兩個不同的數據結構:Thread_info和進程的內核堆棧。
二,進程的創建
fork、vfork和clone三個系統調用都可以創建一個新進程,而且都是通過調用do_fork來實現進程的創建。 ? ?
fork在父進程和子進程之間各返回一次。
fork出的子進程從哪里開始執行? fork的進程給了一個系統調用,和傳統系統調用創建進程過程時不同。ret_from_fork
?
p指向的是ret_from_fork,所以是從這里開始執行的。
復制內核堆棧的時候是復制的pt_regs,即只復制了SAVE_ALL相關的那一部分,即系統調用壓棧的那一部分。
pt_regs里面內容有:
Entry(ret_from_fork):
最終會跳轉到syscall_exit,這之前的內核堆棧狀態和syscall_call的一致,然后返回用戶態,變成子進程的用戶態。
?
創建新進程通過復制已有進程來實現,子進程的許多數據結構需要修改,需要一個新的內核堆棧,該內核堆棧一部分也是從父進程復制過來的,以為需要返回進程。
子進程的fork返回0,因為“childregs->ax?=?0;?”。
系統調用內核處理函數:sys_fork,sys_clone,sys_vfork。
復制的內核堆棧時只復制了內核堆棧最棧底的部分,例如:SAVE_ALL,int指令等。
使用gdb跟蹤創建新進程的過程
各種函數:
?
進程創建的分析
- 復制一個PCB——task_struct
- 要給新進程分配一個新的內核堆棧
3.要修改復制過來的進程數據,比如pid、進程鏈表等,見copy_process內部。
系統調用內核處理函數sys_fork,sys_vfrok,sys_clone,其實最終執行的都是do_fork。
do_fork里有:
三,心得
在Linux內核的分析里,線程被視作一種特殊的進程,和一般的操作系統里不同,進程的創建和調度都是關鍵的動作。