<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁(yè) > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > fork函數(shù)的寫時(shí)拷貝

          fork函數(shù)的寫時(shí)拷貝

          作者: 時(shí)間:2016-12-01 來(lái)源:網(wǎng)絡(luò) 收藏
          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ǔ)空間的過(guò)程中采用了寫時(shí)拷貝技術(shù)(具體的操作大小是按著頁(yè)控制的),該技術(shù)主要是將多進(jìn)程中同樣的對(duì)象(數(shù)據(jù))在物理存儲(chǔ)其中只有一個(gè)物理存儲(chǔ)空間,而當(dāng)其中的某一個(gè)進(jìn)程試圖對(duì)該區(qū)域進(jìn)行寫操作時(shí),內(nèi)核就會(huì)在物理存儲(chǔ)器中開辟一個(gè)新的物理頁(yè)面,將需要寫的區(qū)域內(nèi)容復(fù)制到新的物理頁(yè)面中,然后對(duì)新的物理頁(yè)面進(jìn)行寫操作。這時(shí)就是實(shí)現(xiàn)了對(duì)不同進(jìn)程的操作而不會(huì)產(chǎn)生影響其他的進(jìn)程,同時(shí)也節(jié)省了很多的物理存儲(chǔ)器。
          #include
          #include
          #include
          #include
          #include
          #include
          int main()
          {
          char p = g;
          int number = 11;
          if(fork()==0) /*子進(jìn)程*/
          {
          p = c; /*子進(jìn)程對(duì)數(shù)據(jù)的修改*/
          printf("p = %c , number = %d ",p,number);
          exit(0);
          }
          /*父進(jìn)程*/
          number = 14; /*父進(jìn)程對(duì)數(shù)據(jù)修改*/
          printf("p = %c , number = %d ",p,number);
          exit(0);
          }
          編譯調(diào)試:
          [gong@Gong-Computer cprogram]$ gcc -g TestWriteCopyTech.c -o TestWriteCopyTech
          [gong@Gong-Computer cprogram]$ ./TestWriteCopyTech
          p = g , number = 14 -----父進(jìn)程打印內(nèi)容
          [gong@Gong-Computer cprogram]$ p = c , number = 11 -----子進(jìn)程打印內(nèi)容
          原因分析:
          由于存在企圖進(jìn)行寫操作的部分,因此會(huì)發(fā)生寫時(shí)拷貝過(guò)程,子進(jìn)程中對(duì)數(shù)據(jù)的修改,內(nèi)核就會(huì)創(chuàng)建一個(gè)新的物理內(nèi)存空間。然后再次將數(shù)據(jù)寫入到新的物理內(nèi)存空間中。可知,對(duì)新的區(qū)域的修改不會(huì)改變?cè)械膮^(qū)域,這樣不同的空間就區(qū)分開來(lái)。但是沒(méi)有修改的區(qū)域仍然是多個(gè)進(jìn)程之間共享。
          fork函數(shù)的代碼段基本是只讀類型的,而且在運(yùn)行階段也只是復(fù)制,并不會(huì)對(duì)內(nèi)容進(jìn)行修改,因此父子進(jìn)程是共享代碼段,而數(shù)據(jù)段、Bss段、堆棧段等會(huì)在運(yùn)行的過(guò)程中發(fā)生寫過(guò)程,這樣就導(dǎo)致了不同的段發(fā)生相應(yīng)的寫時(shí)拷貝過(guò)程,實(shí)現(xiàn)了不同進(jìn)程的獨(dú)立空間。
          但是需要注意的是文件操作,由于文件的操作是通過(guò)文件描述符表、文件表、v-node表三個(gè)聯(lián)系起來(lái)控制的,其中文件表、v-node表是所有的進(jìn)程共享,而每個(gè)進(jìn)程都存在一個(gè)獨(dú)立的文件描述符表。父子進(jìn)程虛擬存儲(chǔ)空間的內(nèi)容是大致相同的,父子進(jìn)程是通過(guò)同一個(gè)物理區(qū)域存儲(chǔ)文件描述符表,但如果修改文件描述符表,也會(huì)發(fā)生寫時(shí)拷貝操作,只有這樣才能保證子進(jìn)程中對(duì)文件描述符的修改,不會(huì)影響到父進(jìn)程的文件描述符表。例如close操作,因?yàn)閏lose會(huì)導(dǎo)致文件的描述符的值發(fā)生變化,相當(dāng)于發(fā)生了寫操作,這是產(chǎn)生了寫時(shí)拷貝過(guò)程,實(shí)現(xiàn)新的物理空間,然后再次發(fā)生close操作,這樣就不會(huì)產(chǎn)生子進(jìn)程中文件描述符的關(guān)閉而導(dǎo)致父進(jìn)程不能訪問(wèn)文件。
          測(cè)試函數(shù):
          #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) //子進(jìn)程
          {
          fd = 1;//stdout
          write(fd,s,7);
          exit(0);
          }
          //父進(jìn)程
          read(fd,c,2);
          c[2]=看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();