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