linux中的fork內核實現分析

張建幫 原創作品轉載請註明出處 《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000

這一次我們來聊聊系統調用中的fork,以便更深入地理解 linux中的調用流程與具體的實現(以內核linux-3.18.6爲例,源代碼點這裏)。

在 Linux 操作系統中,每個進程被創建的時候,內核會給這個進程分配一個進程描述符結構,即PCB ,進程控制塊。它保存了這個進程的狀態,標識符,打開的文件,等待的信號,文件系統等待的資源信息。每個進程描述符都表示一個獨立的進程。在操作系統中,每個進程的進程描述都被加入到一個雙向鏈表的任務隊列中,由操作系統決定哪個進程可以佔用 CPU ,哪個進程應該讓出 CPU 。在 Linux 中,一個進程的進程描述符結構如下圖所示:

task_struct結構圖

可以看到,它是一個很複雜的數據結構,我們將在下面進行更詳細的分析。

關於linux中的系統調用的具體流程,我的前兩篇博客已經講得比較清楚了,因此這裏只對fork 系統調用做一些簡單的介紹。

fork 函數有着一次調用,兩次返回的特點。在父進程中,fork 調用將會返回子進程的 PID ,而在子進程中,fork 調用返回的是0。

fork系統調用的調用過程簡單描述如下:

  1. 首先是開始,父進程調用 fork ,因爲這是一個系統調用,所以會導致 int 軟中斷,進入內核空間;

  2. 內核根據系統調用號,調用 sys_clone(有的版本可能是sys_fork,無論是哪種,最後都是通過do_fork函數實現的) 系統調用,而 sys_clone 系統調用則會調用do_fork 函數來實現其功能。do_fork這個函數是 fork 的主要執行部分。在 do_fork 中,首先做一些錯誤檢查工作和準備複製父進程的初始化工作。然後 do_fork函數調用 copy_process函數完成相關功能

  3. copy_process 函數是對父進程的內核狀態和相關的資源進行復制的主要函數,它會調用 copy_thread 函數,複製父進程的執行狀態,包括相關寄存器的值,指令指針和建立相關的棧

  4. copy_thread函數還幹了一件事,就是把0值寫入到寄存器中,然後將其IP指向一個彙編函數 ret_from_fork 。所以在子進程運行的時候,雖然代碼和父進程的代碼是一致的,但是還是有些區別:在copy_thread執行完畢後,子進程的第一條指令就被設置爲了ret_from_fork,進行一些清理工作,然後退出到用戶空間。用戶空間函數可以通過寄存器中的值得到 fork 系統調用的返回值爲0。

  5. 而在父進程中,copy_process執行完畢後,將會返回一個指向子進程的指針。然後回到 do_fork 函數,當copy_process 函數成功返回到do_fork函數時,子進程在do_fork中被喚醒,然後加入到進程調度隊列中。此外,do_fork 還會返回子進程 的 PID

正所謂“一圖勝千言”,各位看官們如果對上面的大段文字不管興趣的話,下面的流程圖可能會讓你一目瞭然:(箭頭代表調用函數之間的調用)
流程圖

基本上,這幅圖像配合上面的文字說明,已經將fork的系統調用實現的主體部分或者說一些關鍵的地方已經講得比較明白了,若是想更進一步的瞭解其中的細節,還是推薦去閱讀linux的源代碼,爲了方便各位網友,我還是再把源代碼的鏈接貼一遍:linux源碼

另外,如果看想看上面這些函數的相關源碼,可以參看下面的這篇文章,寫的挺好的。

參考:
http://blog.tonychow.me/blog/2013/06/27/linuxzhong-forkxi-tong-diao-yong-fen-xi/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章