在建立程序時,會用到fork 或vfork 建立子程序
1)copy- on write(fork)
fork之後exec之前,父子程序的虛拟空間不同,但其對應的實體空間是同一個!
兩個程序用的是相同的實體空間(記憶體區),子程序的代碼段、資料段、堆棧都是指向父程序的實體空間! (從左往右的大箭頭表示的建立子程序的複制動作)
當父子程序中有更改相應段的行為發生時,再為子程序相應的段配置設定實體空間!
如果是在子程序中調用了exec,由于兩者執行的代碼不同,子程序的代碼段也會配置設定單獨的實體空間。
fork函數建立子程序後,子程序往往要調用一種exec函數以執行另一個程式,當程序調用一種exec函數時,該程序完全由新程式代換,而新程式則從其main函數開始執行,因為調用exec并不建立新程序,是以前後的程序id 并未改變,exec隻是用另一個新程式替換了目前程序的正文,資料,堆和棧段。
2 ) vfork
1 vfork 不會将父程序的位址空間完全複制到子程序中,也不會複制頁表。在子程序調用ecec 或者exit的之前,子程式會在父程式的空間運作,父程序阻塞。挂起)
2 vfork保證子程序先運作(fork不能保證),在她調用exec或exit之後父程序才可能被排程運作。如果在調用這兩個函數之前子程序依賴于父程序的進一步動作,則會導緻死鎖。(從左到右的箭頭表示的是共享)
///
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int glob = 6;
int main()
{
int var;
pid_t pid;
var = 88;
printf("before fork\n");
if((pid = fork()) < 0)
{
perror("fork");
return 1;
}
else if(pid == 0)// 子程序
{
glob++;
var++;
_exit(0);
}
else // 父程序
{
printf("pid=%d,glob=%d,var=%d\n", getpid(),glob,var);
exit(0);
}
}
/*
fork時,由于glob 和 val 沒有發生變化 ,說明父子程序在資料發生改變時,會獨立配置設定給子程序一塊兒實體空間。
vfork 兩個資料發生了改變,表示子程序在父程序空間中運作。
*/
結果:
before fork
father process pid=4681,glob=6,var=88
son process pid=4682,glob=7,var=89
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int glob = 6;
int main()
{
int var;
pid_t pid;
var = 88;
printf("before vfork\n");
if((pid = vfork()) < 0)
{
perror("vfork");
return 1;
}
else if(pid == 0)// 子程序
{
glob++;
var++;
printf("son process pid=%d,glob=%d,var=%d\n", getpid(),glob,var);
_exit(0);
}
else // 父程序
{
printf("father process pid=%d,glob=%d,var=%d\n", getpid(),glob,var);
exit(0);
}
}
結果:
before vfork
son process pid=4670,glob=7,var=89
father process pid=4669,glob=7,var=89