fork和vfork,return和exit的理解
fork和vfork的差別:
1、fork是創(chuàng)建一個(gè)子進(jìn)程,并把父進(jìn)程的內(nèi)存數(shù)據(jù)copy到子進(jìn)程中。
vfork是創(chuàng)建一個(gè)子進(jìn)程,并和父進(jìn)程的內(nèi)存數(shù)據(jù)share一起。
2、vfork是這樣的工作的:
(1)、保證子進(jìn)程先執(zhí)行。
(2)、當(dāng)子進(jìn)程調(diào)用exit()或exec()后,父進(jìn)程往下執(zhí)行。
3、fork后來(lái)采用的優(yōu)化技術(shù),這樣,對(duì)于fork后并不是馬上拷貝內(nèi)存,而是只有你在需要改變的時(shí)候,才會(huì)從父進(jìn)程中拷貝到子進(jìn)程中,這樣fork后立馬執(zhí)行exec的成本就非常小了。而vfork因?yàn)楣蚕韮?nèi)存所以比較危險(xiǎn)。
?
為什么會(huì)出現(xiàn)vfork?
原因是: 起初只有fork,但是很多程序在fork一個(gè)子進(jìn)程后就exec一個(gè)外部程序,于是fork需要copy父進(jìn)程的數(shù)據(jù)這個(gè)動(dòng)作就變得毫無(wú)意了,而且還很重,所以,搞出了個(gè)父子進(jìn)程共享的vfork。所以,vfork本就是為了exec而生。
exit與return的區(qū)別:
exit函數(shù)在頭文件stdlib.h中。
exit(0):正常運(yùn)行程序并退出程序;
exit(1):非正常運(yùn)行導(dǎo)致退出程序;
return():返回函數(shù),若在main主函數(shù)中,則會(huì)退出函數(shù)并返回一值,可以寫(xiě)為return(0),或return 0。
詳細(xì)說(shuō):
1. return返回函數(shù)值,是關(guān)鍵字;exit是一個(gè)函數(shù)。
2. return是語(yǔ)言級(jí)別的,它表示了調(diào)用堆棧的返回;而exit是系統(tǒng)調(diào)用級(jí)別的,它表示了一個(gè)進(jìn)程的結(jié)束。
3. return是函數(shù)的退出(返回);exit是進(jìn)程的退出。
4. return是C語(yǔ)言提供的,exit是操作系統(tǒng)提供的(或者函數(shù)庫(kù)中給出的)。
5. return用于結(jié)束一個(gè)函數(shù)的執(zhí)行,將函數(shù)的執(zhí)行信息傳出個(gè)其他調(diào)用函數(shù)使用;exit函數(shù)是退出應(yīng)用程序,刪除進(jìn)程使用的內(nèi)存空間,并將應(yīng)用程序的一 個(gè)狀態(tài)返回給OS,這個(gè)狀態(tài)標(biāo)識(shí)了應(yīng)用程序的一些運(yùn)行信息,這個(gè)信息和機(jī)器和操作系統(tǒng)有關(guān),一般是?0?為正常退出,非0?為非正常退出。
6. 非主函數(shù)中調(diào)用return和exit效果很明顯,但是在main函數(shù)中調(diào)用return和exit的現(xiàn)象就很模糊,多數(shù)情況下現(xiàn)象都是一致的。
?
為什么return會(huì)掛掉,exit()不會(huì)?
從上面我們知道,結(jié)束子進(jìn)程的調(diào)用是exit()而不是return,如果你在vfork中return了,那么,這就意味main()函數(shù)return了,注意因?yàn)?/span>函數(shù)棧父子進(jìn)程共享,所以整個(gè)程序的棧就出現(xiàn)問(wèn)題了。如果你在子進(jìn)程中return,那么基本是下面的過(guò)程:
(1)、首先子進(jìn)程的main() 函數(shù) return了。
(2)、而main()函數(shù)return后,通常會(huì)調(diào)用 exit()或相似的函數(shù)(如:exitgroup())。
(3)、這時(shí),父進(jìn)程收到子進(jìn)程exit(),開(kāi)始從vfork返回,但是父進(jìn)程的棧都被子進(jìn)程干廢掉了,你讓我怎么執(zhí)行?(注:棧會(huì)返回一個(gè)詭異一個(gè)棧地址,對(duì)于某些內(nèi)核版本的實(shí)現(xiàn),直接報(bào)“棧錯(cuò)誤”,然而,對(duì)于某些內(nèi)核版本的實(shí)現(xiàn),于是有可能會(huì)再次調(diào)用main(),于是進(jìn)入了一個(gè)無(wú)限循環(huán)的結(jié)果,直到vfork 調(diào)用返回 error)
再回到 return 和 exit,return會(huì)釋放局部變量,并彈棧,回到上級(jí)函數(shù)執(zhí)行。exit直接退掉。如果你用c++ 你就知道,return會(huì)調(diào)用局部對(duì)象的析構(gòu)函數(shù),exit不會(huì)。(注:exit不是系統(tǒng)調(diào)用,是glibc對(duì)系統(tǒng)調(diào)用 _exit()或_exitgroup()的封裝)。
可見(jiàn),子進(jìn)程調(diào)用exit() 沒(méi)有修改函數(shù)棧,所以,父進(jìn)程得以順利執(zhí)行。
?
內(nèi)核代碼分析:
linux創(chuàng)建子進(jìn)程實(shí)際是一個(gè)復(fù)制父進(jìn)程的過(guò)程。所以更貼切的說(shuō)法是clone。linux一開(kāi)始使用fork的原因是當(dāng)時(shí)clone這個(gè)詞還沒(méi)有流行。 實(shí)際存在fork,clone,vfork 三個(gè)系統(tǒng)調(diào)用。fork是完全復(fù)制,clone則是有選擇的復(fù)制,vfork則完全使用父進(jìn)程的資源。可以理解vfork是創(chuàng)建的線程。 vfork的出現(xiàn)主要是為了立即就執(zhí)行exec的程序考慮的。但是后來(lái)的kernel都支持copy_on_write ,所以vfork提高效率的機(jī)制也沒(méi)有那么明顯了。
內(nèi)核中三個(gè)系統(tǒng)調(diào)用最后都是調(diào)用do_fork:
fork:return do_fork(SIGCHLD, regs.esp, s, 0);
clone:return do_fork(clone_flags, newsp, s, 0);
vfork: return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, s, 0);
?
#define CLONE_VFORK 0x00004000 ?/* set if the parent wants the child to wake it up on mm_release*/
#define CLONE_VM 0x00000100 ?/* set if VM shared between processes */
上面兩個(gè)宏指出:vfork 要求子進(jìn)程執(zhí)行mm_release 后喚醒 父進(jìn)程, 并且共享虛擬內(nèi)存
?
為什么要求子進(jìn)程先行呢?
拿虛擬內(nèi)存做比方。 進(jìn)程需要有結(jié)構(gòu)管理自己的虛擬內(nèi)存空間, 該結(jié)構(gòu)在進(jìn)程 結(jié)構(gòu)體 task_struct 中就是一個(gè)mm_struct 類(lèi)型的指針。fork的時(shí)候內(nèi)核會(huì)新建結(jié)構(gòu)體,將該mm_struct 本身以及下級(jí)結(jié)構(gòu)都復(fù)制一份,并設(shè)置子進(jìn)程的mm_struct 指向新的內(nèi)存。而vfork則只是復(fù)制了task_struct 本身,并沒(méi)有遞歸下去。簡(jiǎn)單說(shuō)就是:fork復(fù)制了內(nèi)存,vfork復(fù)制了指針。
?
相關(guān)例子:
fork
?vfork
運(yùn)行結(jié)果為:
fork運(yùn)行結(jié)果:
vfork運(yùn)行結(jié)果:
1、return返回時(shí)出錯(cuò):
2、exit返回結(jié)果:
運(yùn)行結(jié)果說(shuō)明:vfrok時(shí)父、子進(jìn)程共享數(shù)據(jù)段,fork時(shí)是進(jìn)行拷貝。如果,vfork子進(jìn)程中,使用return返回時(shí),出現(xiàn)段錯(cuò)誤。
?
轉(zhuǎn)載于:https://blog.51cto.com/760470897/1790060
總結(jié)
以上是生活随笔為你收集整理的fork和vfork,return和exit的理解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【转】js之iframe子页面与父页面通
- 下一篇: 2016及以后的自动化测试趋势 -《测试