複製鏈接
請複製以下鏈接發送給好友

vfork

鎖定
vfork,計算機術語,意思是建立一個新的進程
中文名
建立一個新的進程
外文名
vfork
相關函數
wait,execve
頭文件
#include

vfork簡介

vfork(建立一個新的進程)
相關函數wait,execve
頭文件 #include<unistd.h>
定義函數pid_t vfork(void);

vfork函數説明

vfork()會產生一個新的子進程.但是vfork創建的子進程與父進程共享數據段,而且由vfork()創建的
子進程將先於父進程運行.fork()的使用詳見百度詞條fork().
vfork()用法與fork()相似.但是也有區別,具體區別歸結為以下3點:
1. fork():子進程拷貝父進程的數據段,代碼段. vfork():子進程與父進程共享數據段.
2. fork():父子進程的執行次序不確定.
vfork():保證子進程先運行,在調用exec或_exit之前與父進程數據是共享的,在它調用exec
或_exit之後父進程才可能被調度運行。
3. vfork()保證子進程先運行,在她調用exec或_exit之後父進程才可能被調度運行。如果在
調用這兩個函數之前子進程依賴於父進程的進一步動作,則會導致死鎖
4.當需要改變共享數據段中變量的值,則拷貝父進程。
下面通過幾個例子加以説明:

vfork返回值

如果vfork()成功則在父進程會返回新建立的子進程代碼(PID),
而在新建立的子進程中則返回0。如果vfork失敗則直接返回-1,失
敗原因存於errno中。
EAGAIN 進程數已達系統規定上限
ENOMEM內存不足,無法配置核心所需的數據結構空間。

vfork範例

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<wait.h>

intmain(
void)
{
pid_tpid;
if((pid=vfork())<0){
perror("vforkisfailed");
exit(1);
}elseif(pid==0){

printf("thisischildprocess\n");
exit(0);
}else{
printf("thisisparentprocess\n");
if(wait(NULL)==-1){
perror("failtowait");
exit(1);
}
}

return0;
}
執行
this is child process
this is parent process
注:如果在子程序中不加exit語句,程序會一直循環執行下去,直到進程號被分配完才會退出

vfork主要區別

vfork用於創建一個新進程,而該新進程的目的是exec一個新進程,vfork和fork一樣都創建一個子進程,但是它並不將父進程地址空間完全複製到子進程中,不會複製頁表。因為子進程會立即調用exec,於是也就不會存放該地址空間。不過在子進程中調用exec或exit之前,他在父進程的空間中運行。
為什麼會有vfork,因為以前的fork當它創建一個子進程時,將會創建一個新的地址空間,並且拷貝父進程的資源,而往往在子進程中會執行exec調用,這樣,前面的拷貝工作就是白費力氣了,這種情況下,聰明的人就想出了vfork,它產生的子進程剛開始暫時與父進程共享地址空間(其實就是線程的概念了),因為這時候子進程父進程的地址空間中運行,所以子進程不能進行寫操作,並且在兒子“霸佔”着老子的房子時候,要委屈老子一下了,讓他在外面歇着(阻塞),一旦兒子執行了exec或者exit後,相當於兒子買了自己的房子了,這時候就相當於分家了。
vfork和fork之間的另一個區別是: vfork保證子進程先運行,在她調用exec或exit之後父進程才可能被調度運行。如果在調用這兩個函數之前子進程依賴於父進程的進一步動作,則會導致死鎖。由此可見,這個系統調用是用來啓動一個新的應用程序。其次,子進程在vfork()返回後直接運行在父進程的棧空間,並使用父進程的內存和數據。這意味着子進程可能破壞父進程的數據結構或棧,造成失敗。
為了避免這些問題,需要確保一旦調用vfork(),子進程就不從當前的棧框架中返回,並且如果子進程改變了父進程的數據結構就不能調用exit函數。子進程還必須避免改變全局數據結構或全局變量中的任何信息,因為這些改變都有可能使父進程不能繼續。通常,如果應用程序不是在fork()之後立即調用exec(),就有必要在fork()被替換成vfork()之前做仔細的檢查。
用vfork函數創建子進程後,子進程往往要調用一種exec函數以執行另一個程序,當進程調用一種exec函數時,該進程完全由新程序代換,而新程序則從其main函數開始執行,因為調用exec並不創建新進程,所以前後的進程id 並未改變,exec只是用另一個新程序替換了當前進程的正文,數據,堆和棧段。