Linux fork的寫時(shí)復(fù)制

看下面的代碼
#include???
#include???
#include???
#include???
#include???
#include???
#include?
#include?
??
int?main(){??
????????int?fd;??
????????char?c[10];??
????????char?*child?=?"#>Child.....output\n";??
??
????????fd?=?open("foobar.txt",O_RDWR|O_CREAT,0666);??
????????printf("fd:%d\n",fd);?
????????write(fd,"foobar.txt",7);
????????close(fd);
????????//父進(jìn)程??
????????fd?=?open("foobar.txt",O_RDONLY,0);
????????printf("fd:%d\n",fd);
????????if(fork()==0)//子進(jìn)程
????????{??
????????????????fd?=?1;//stdout
????????????????write(fd,child,strlen(child)+1);
????????????????exit(0);??
????????}??
????????printf("fd:%d\n",fd);
????????read(fd,c,sizeof(c));
????????close(fd);?
????????c[10]='\0';??
????????printf("c?=?%s\n",c);??
????????exit(0);??
}??
先不要往下看,猜測(cè)下這個(gè)代碼的輸出是啥
特別是 fd 在fork出來的進(jìn)程里面進(jìn)行了修改,那是不是讀出來的內(nèi)容會(huì)是不對(duì)的呢?
實(shí)際輸出如下:
weiqifa@bsp-ubuntu1804:~/linux$?gcc?forkc4.c?&&?./a.out
fd:3
fd:3
fd:3
c?=?foobar
#>Child.....output
weiqifa@bsp-ubuntu1804:~/linux$
這涉及一個(gè)知識(shí)點(diǎn),叫做寫時(shí)復(fù)制,就是在使用的使用,我再分配實(shí)際的物理內(nèi)存給子進(jìn)程,如果沒有需要使用的資源,那我就還是用父進(jìn)程的東西。
fork函數(shù)用于創(chuàng)建子進(jìn)程,典型的調(diào)用一次,返回兩次的函數(shù),其中返回子進(jìn)程的PID是0,其中調(diào)用進(jìn)程返回了子進(jìn)程的PID,而子進(jìn)程則返回了0,這是一個(gè)比較有意思的函數(shù)。
但是兩個(gè)進(jìn)程的執(zhí)行順序是不定的。fork()函數(shù)調(diào)用完成以后父進(jìn)程的虛擬存儲(chǔ)空間被拷貝給了子進(jìn)程的虛擬存儲(chǔ)空間,因此也就實(shí)現(xiàn)了共享文件等操作。
但是虛擬的存儲(chǔ)空間映射到物理存儲(chǔ)空間的過程中采用了寫時(shí)拷貝技術(shù)(具體的操作大小是按著頁控制的),該技術(shù)主要是將多進(jìn)程中同樣的對(duì)象(數(shù)據(jù))在物理存儲(chǔ)其中只有一個(gè)物理存儲(chǔ)空間,而當(dāng)其中的某一個(gè)進(jìn)程試圖對(duì)該區(qū)域進(jìn)行寫操作時(shí),內(nèi)核就會(huì)在物理存儲(chǔ)器中開辟一個(gè)新的物理頁面,將需要寫的區(qū)域內(nèi)容復(fù)制到新的物理頁面中,然后對(duì)新的物理頁面進(jìn)行寫操作。這時(shí)就是實(shí)現(xiàn)了對(duì)不同進(jìn)程的操作而不會(huì)產(chǎn)生影響其他的進(jìn)程,同時(shí)也節(jié)省了很多的物理存儲(chǔ)器。
寫時(shí)復(fù)制的技術(shù)讓操作系統(tǒng)大大降低了實(shí)際的物理內(nèi)存空間。
參考:
https://www.cnblogs.com/wuchanming/p/4495479.html

微信掃描二維碼,關(guān)注我的公眾號(hào)
