麗水市蓮都區(qū)建設分局網站優(yōu)幫云排名自動扣費
目錄
- 一、fork函數
- 二、vfork函數
- 1.函數的原理
- 2.函數的隱患
- 3.解決函數隱患的方法
??在Linux的進程學習中,常使用fork函數來創(chuàng)建子進程,但其實還有一個vfork函數也可以創(chuàng)建子進程。但是這兩個函數的實現機制不同,fork函數使用了寫實拷貝技術,而vfork函數不是這樣。
??在看本文前,需要對虛擬內存有一定的了解,因為創(chuàng)建子進程離不開虛擬內存。
一、fork函數
pid_t fork(void);
??fork函數運用的是寫實拷貝技術,子進程不但會復制父進程的pcb的信息,也會復制父進程的虛擬空間和頁表。
??所以在剛創(chuàng)建子進程后,子進程和父進程映射的是同一塊物理內存,因此實現了父子進程代碼共享。
??但是如果子進程需要修改數據,比如程序中有一個變量a,子進程想要修改a的數據,那么系統就會給子進程在物理內存重新開辟一塊空間存儲a的數據,子進程要修改就修改自己的a,不要去修改父進程的a。這樣就保證了父子進程的數據獨有。
二、vfork函數
pid_t vfork(void);
1.函數的原理
??vfork與fork相比,vfork創(chuàng)建的子進程只復制了父進程的pcb,并沒有復制虛擬空間和頁表。父子進程使用的是同一塊虛擬空間和頁表,因此父子進程映射的是同一塊物理內存。
2.函數的隱患
(1)由于vfrok創(chuàng)建的子進程和父進程共用虛擬空間和頁表,因此訪問的是同一個內存空間,那么一旦子進程改變了某個數據,父進程的數據同樣會隨之改變。
(2)更嚴重的問題是,會導致調用?;靵y。
??當程序運行一個函數時,就要先將函數壓入函數調用棧,當運行完畢才會將函數出棧。vfork創(chuàng)建的父子進程共用調用棧,當父進程運行A函數時,需要把A函數壓入函數調用棧,如果在A函數還沒運行完的時候時間片就用完了,就需要切換到子進程。子進程運行的是B函數,子進程還沒運行完B函數的時候時間片就用完了,因此切換到父進程運行。父進程在這個時間片把函數A運行完了,因此函數A需要出棧,但此時函數調用棧的棧頂是B函數,就會將B函數出棧,從而造成調用?;靵y。
??結合下圖來理解:
3.解決函數隱患的方法
??既然vfork函數如上所述的缺點,那么自然要有相應的解決方法。
??如果用vfrok函數創(chuàng)建子進程,當子進程運行時,父進程會被阻塞。父進程被阻塞到什么時候?一直到子進程退出,或者是子進程進行了程序替換后。這樣就可以解決上面的缺點。