新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > fork函數的寫時拷貝

        fork函數的寫時拷貝

        作者: 時間:2016-12-01 來源:網絡 收藏
        fork函數用于創建子進程,典型的調用一次,返回兩次的函數,其中返回子進程的PID和0,其中調用進程返回了子進程的PID,而子進程則返回了0,這是一個比較有意思的函數,但是兩個進程的執行順序是不定的。fork 函數調用完成以后父進程的虛擬存儲空間被拷貝給了子進程的虛擬存儲空間,因此也就實現了共享文件等操作。但是虛擬的存儲空間映射到物理存儲空間的過程中采用了寫時拷貝技術(具體的操作大小是按著頁控制的),該技術主要是將多進程中同樣的對象(數據)在物理存儲其中只有一個物理存儲空間,而當其中的某一個進程試圖對該區域進行寫操作時,內核就會在物理存儲器中開辟一個新的物理頁面,將需要寫的區域內容復制到新的物理頁面中,然后對新的物理頁面進行寫操作。這時就是實現了對不同進程的操作而不會產生影響其他的進程,同時也節省了很多的物理存儲器。
        #include
        #include
        #include
        #include
        #include
        #include
        int main()
        {
        char p = g;
        int number = 11;
        if(fork()==0) /*子進程*/
        {
        p = c; /*子進程對數據的修改*/
        printf("p = %c , number = %d ",p,number);
        exit(0);
        }
        /*父進程*/
        number = 14; /*父進程對數據修改*/
        printf("p = %c , number = %d ",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
        #include
        #include
        #include
        #include
        #include
        #include
        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]= 主站蜘蛛池模板: 通山县| 奉节县| 明光市| 曲靖市| 长顺县| 慈利县| 香格里拉县| 肇庆市| 泾源县| 灯塔市| 商丘市| 临朐县| 无为县| 新田县| 抚州市| 望城县| 邓州市| 禹城市| 宁德市| 东乌珠穆沁旗| 万山特区| 惠东县| 克什克腾旗| 海淀区| 仁化县| 乡宁县| 石阡县| 天长市| 左权县| 宜黄县| 平罗县| 罗甸县| 左云县| 常宁市| 民乐县| 逊克县| 贵溪市| 内乡县| 昭平县| 普安县| 城口县|