1.在Linux中進程的創(chuàng)建方式
在linux系統(tǒng)中,新的進程是通過已存在的父進程復制而來的。
- 當一個子進程被成功創(chuàng)建,其虛擬地址空間的信息與其父進制的虛擬空間信息是相同的(這意味著它們的代碼和數(shù)據(jù)是一致的)。
- 通過執(zhí)行exec系列的函數(shù),可以用一個新程序的虛擬地址空間信息來更新子進程的虛擬地址空間信息。
2.fork函數(shù)原理
2.1 fork函數(shù)原型
pid_t fork(void);
功能:創(chuàng)建一個新的進程。
參數(shù):
無。
返回值:
fork函數(shù)調用一次返回兩次。
-
父進程:返回子進程PID。
-
子進程:返回0。
-
失敗:返回-1。
2.2 fork函數(shù)實現(xiàn)原理
2.3 父子進程虛擬地址空間(mm_struct)之間的關系
- 父子進程各自擁有自己獨立的虛擬地址空間。
- 父子進程共享代碼段(只讀)。
- 采用寫時拷貝(copy-on-write)技術創(chuàng)建子進程虛擬地址空間。
2.4 寫時拷貝(copy-on-write)技術
傳統(tǒng)fork函數(shù)缺點:
- 復制子進程虛擬地址空間時,存在大量拷貝,效率很低。
- 子進程立馬需要執(zhí)行execv函數(shù)替換虛擬地址空間內容,導致上一步復制子進程虛擬地址空間變得多余。
什么是寫時拷貝?
寫時拷貝是指父進程在創(chuàng)建子進程時,只創(chuàng)建虛擬地址空間,不為子進程分配實際的內存,父進程和子進程之間共享相同的物理內存頁面。
當父進程或者子進程對虛擬地址空間對應的內存進行修改時才會分配實際內存。
寫時拷貝技術優(yōu)點:
- 節(jié)省內存開銷。
- 提高創(chuàng)建進程效率。
拷貝前
拷貝后
2.5 父子進程如何共享文件(files_struct)
FD_CLOSEXEC文件標志?
子進程和父進程共享文件是一種不安全的行為,如果子進程調用exec家族函數(shù),子進程的虛擬機制空間被新的程序替換,如果子進程還保留父進程的文件描述符表,后果很嚴重。
文件設置FD_CLOSEXEC文件標志后,子進程調用exec家族函數(shù),該文件會被關閉。
如何設置FD_CLOSEXEC文件標志?
- 方法1:open函數(shù)帶上O_CLOSEXEC標志。
如:open(“file”, O_RDWR | O_CREAT | O_TRUNC | O_CLOSEXEC, 0644 );
- 方法2:fcntl函數(shù)F_SETFD操作設置。
3.vfork函數(shù)原理
3.1 vfork函數(shù)原型
pid_t vfork(void);
功能:fork函數(shù)創(chuàng)建一個新的子進程,該子進程與父進程共享相同的地址空間。
參數(shù):
無。
返回值:
vfork函數(shù)調用一次返回兩次。
- 父進程:返回子進程PID。
- 子進程:返回0。
- 失敗:返回-1。
3.2 vfork和fork函數(shù)區(qū)別?
- vfork函數(shù)創(chuàng)建子進程和父進程共享地址空間。
- 使用vfork函數(shù)創(chuàng)建的子進程則會暫停父進程的執(zhí)行,直到子進程調用exec()或者_exit()函數(shù)退出或替換自己的地址空間。
不推薦使用vfork函數(shù)!!!
vfork函數(shù)由于子進程和父進程共享地址空間,vfork比傳統(tǒng)fork函數(shù)效率高。隨著寫時復制技術出現(xiàn),這個優(yōu)勢已經(jīng)不存在了。
vfork存在不安全的行為,所以不推薦使用vfork函數(shù)。