1.首次查找_pidmap位圖,爲新子進程分配新的pid
函數
2.複製進程描述符,返回的是新的進程描述符的地址(struct task_struct *p)
spa
3.初始化完成量,vfrok主要用excv,父進程的虛擬地址空間對其沒有用處,因此實現方式爲在子進程退出或者替換後父進程纔開始執行
線程
4.若是設置了vfork,則調用wait(父進程)3d
5.free_pidmap(pid):blog
6.返回子進程pid。繼承
1.檢查flag位的合法性進程
2.爲子進程獲取進程描述符圖片
開闢內核棧+thread_info 通常大小爲8kget
將current的值賦給子進程
源碼
3.檢查線程數量,設置一些關鍵字,保存新的pid
4.用系統調用時cpu寄存器中的值初始化新線程,將exa置爲0(fork和clone在子進程的返回值)
5.完成一些字段的設置,將新進程加入到鏈表,將新進程pid加入到散列表
複製父進程每個vm_area_struct,也複製它的頁表,將私有的可寫的頁都標記爲只讀,爲寫時拷貝作準備。
1.判斷是否爲建立線程,若是是線程,直接使用mm = oldmm ,表示線程公用虛擬地址空間
2.對於非線程,爲其建立虛擬地址空間,建立新的局部描述符加入到tsk地址空間,以後調用dup_mmap;
後續須要解決的問題:
1.current是什麼
task_struct 包含了進程全部的信息,current是一個宏,由getCurrent()->task替換,此函數內部是一條彙編指令,在x86體系下經過在內核棧尾部插入thread_info結構,計算偏移量,來查找到當前正在運行的進程描述符。
2.用戶態fork()->內核態sys_fork()的過程是什麼
普通程序調用fork()-->庫函數fork()-->系統調用(fork功能號)-->由功能號在 sys_call_table[]中尋到sys_fork()函數地址-->調用sys_fork(),這就完成拉從用戶態到內核態的變化過程。
總結一下:
看源碼前對fork()只停留在用上,看了以後明白了不少死記硬背的點,也有了本身的理解。主要幾個點,fork的返回值,進程和線程的區別,vfork現階段還暫時沒有用過先記住吧,還包括子進程繼承父進程的信息,還有寫時拷貝的先決條件等。