久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

專注電子技術學習與研究
當前位置:單片機教程網 >> MCU設計實例 >> 瀏覽文章

fork函數的寫時拷貝

作者:公平   來源:本站原創   點擊數:  更新時間:2014年03月14日   【字體:
fork函數用于創建子進程,典型的調用一次,返回兩次的函數,其中返回子進程的PID和0,其中調用進程返回了子進程的PID,而子進程則返回了0,這是一個比較有意思的函數,但是兩個進程的執行順序是不定的。fork 函數調用完成以后父進程的虛擬存儲空間被拷貝給了子進程的虛擬存儲空間,因此也就實現了共享文件等操作。但是虛擬的存儲空間映射到物理存儲空間的過程中采用了寫時拷貝技術(具體的操作大小是按著頁控制的),該技術主要是將多進程中同樣的對象(數據)在物理存儲其中只有一個物理存儲空間,而當其中的某一個進程試圖對該區域進行寫操作時,內核就會在物理存儲器中開辟一個新的物理頁面,將需要寫的區域內容復制到新的物理頁面中,然后對新的物理頁面進行寫操作。這時就是實現了對不同進程的操作而不會產生影響其他的進程,同時也節省了很多的物理存儲器。

 
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/types.h>
#include<sys/stat.h>

 

 
int main()
{
        char p = 'g';
        int number = 11;

        if(fork()==0)      /*子進程*/
        {
                p = 'c';      /*子進程對數據的修改*/

                printf("p = %c , number = %d \n ",p,number);

                exit(0);
        }
       /*父進程*/
        number = 14;  /*父進程對數據修改*/
        printf("p = %c , number = %d \n ",p,number);
        exit(0);
}

 
編譯調試:
[gong@Gong-Computer cprogram]$ gcc -g TestWriteCopyTech.c -o TestWriteCopyTech
[gong@Gong-Computer cprogram]$ ./TestWriteCopyTech 
p = g , number = 14    -----父進程打印內容
 [gong@Gong-Computer cprogram]$ p = c , number = 11    -----子進程打印內容 

原因分析:
由于存在企圖進行寫操作的部分,因此會發生寫時拷貝過程,子進程中對數據的修改,內核就會創建一個新的物理內存空間。然后再次將數據寫入到新的物理內存空間中。可知,對新的區域的修改不會改變原有的區域,這樣不同的空間就區分開來。但是沒有修改的區域仍然是多個進程之間共享。
fork函數的代碼段基本是只讀類型的,而且在運行階段也只是復制,并不會對內容進行修改,因此父子進程是共享代碼段,而數據段、Bss段、堆棧段等會在運行的過程中發生寫過程,這樣就導致了不同的段發生相應的寫時拷貝過程,實現了不同進程的獨立空間。
但是需要注意的是文件操作,由于文件的操作是通過文件描述符表、文件表、v-node表三個聯系起來控制的,其中文件表、v-node表是所有的進程共享,而每個進程都存在一個獨立的文件描述符表。父子進程虛擬存儲空間的內容是大致相同的,父子進程是通過同一個物理區域存儲文件描述符表,但如果修改文件描述符表,也會發生寫時拷貝操作,只有這樣才能保證子進程中對文件描述符的修改,不會影響到父進程的文件描述符表。例如close操作,因為close會導致文件的描述符的值發生變化,相當于發生了寫操作,這是產生了寫時拷貝過程,實現新的物理空間,然后再次發生close操作,這樣就不會產生子進程中文件描述符的關閉而導致父進程不能訪問文件。

 
測試函數:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<sys/wait.h>

 
int main()
{
        int fd;
        char c[3];

 
        char *s = "TestFs";

        fd = open("foobar.txt",O_RDWR,0);

        if(fork()==0)   //子進程
        {
                fd = 1;//stdout
                write(fd,s,7);
                exit(0);
        }
       //父進程
        read(fd,c,2);
        c[2]='\0';
        printf("c = %s\n",c);
        exit(0);
}

 
[gong@Gong-Computer cprogram]$ gcc -g fileshare2.c -o fileshare2
[gong@Gong-Computer cprogram]$ ./fileshare2
c = fo    ----foobar.txt中的內容
[gong@Gong-Computer cprogram]$ TestFs   ---標準輸出 

原因分析:由于父子進程的文件描述符表是相同的,但是在子進程中對fd(文件描述符表中的項)進行了修改,這時會發生寫時拷貝過程,內核在物理內存中分配一個新的頁面存儲子進程原文件描述符fd存在頁面的內容,然后再進修寫操作,實現將fd修改為1,也就是標準輸出。但是父進程的fd并沒有發生改變,還是與其他的子進程共享文件描述符表,因此仍然是對文件foobar.txt進行操作。

因此需要主要fork函數實質上是按著寫時拷貝的方式實現文件的映射,并不是共享,寫時拷貝操作使得內存的需求量大大的減少了,具體的寫時拷貝實現,請參看非常經典的“深入理解計算機系統”的第622頁。
關閉窗口

相關文章

主站蜘蛛池模板: 亚州视频在线 | 日韩欧美在线观看 | 日本啊v在线 | 国产精品久久久久无码av | 91精品久久久久久久 | 蜜臀网| 91精品国产91久久久久久不卞 | 精品美女久久久 | 精品久久久一区 | 欧美xxxx色视频在线观看免费 | 一区二区福利视频 | 日本精品久久久一区二区三区 | 久久精品久久久久久 | 噜噜噜噜狠狠狠7777视频 | 最新日韩精品 | 日韩中文字幕一区二区 | 国产精品三级 | 国产精品久久国产精品 | 久久丝袜视频 | 亚洲视频中文字幕 | 91热在线| 成人小视频在线观看 | av一级| 亚洲一区二区中文字幕 | 国产有码 | 午夜爽爽爽男女免费观看影院 | 久久久精彩视频 | 午夜精品一区二区三区在线视频 | 日日日操 | 一区在线免费视频 | 美女露尿口视频 | 午夜小电影 | 一级片视频免费 | 欧美一级www片免费观看 | 欧美激情亚洲天堂 | 精品久久影院 | 日韩高清一区 | 亚洲一二三视频 | 久久精品成人 | 亚洲精品久久久久中文字幕欢迎你 | 欧美精品一级 |