1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      利用mmap怎么對文件進(jìn)行復(fù)制

      這篇文章將為大家詳細(xì)講解有關(guān)利用mmap怎么對文件進(jìn)行復(fù)制,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對相關(guān)知識(shí)有一定的了解。

      堅(jiān)守“ 做人真誠 · 做事靠譜 · 口碑至上 · 高效敬業(yè) ”的價(jià)值觀,專業(yè)網(wǎng)站建設(shè)服務(wù)10余年為成都玻璃貼膜小微創(chuàng)業(yè)公司專業(yè)提供企業(yè)網(wǎng)站制作營銷網(wǎng)站建設(shè)商城網(wǎng)站建設(shè)手機(jī)網(wǎng)站建設(shè)小程序網(wǎng)站建設(shè)網(wǎng)站改版,從內(nèi)容策劃、視覺設(shè)計(jì)、底層架構(gòu)、網(wǎng)頁布局、功能開發(fā)迭代于一體的高端網(wǎng)站建設(shè)服務(wù)。

      典型的文件復(fù)制的流程是:

      1、讀取(fread)被復(fù)制的文件的內(nèi)容。
      2、寫入(fwrite)到新的文件中去。

      使用mmap進(jìn)行文件復(fù)制的流程則是:

      1、為被復(fù)制的文件已經(jīng)新文件分別進(jìn)行mmap映射。
      2、將被復(fù)制的文件映射的內(nèi)存的內(nèi)容復(fù)制到新文件映射的內(nèi)存。

      在知道了基本原理之后,讓我們看看具體的做法,本文只分析使用mmap進(jìn)行大文件復(fù)制的方法

      具體的做法

      先了解一些使用mmap時(shí),應(yīng)當(dāng)注意的細(xì)節(jié):

      • 文件的大小必須要大于等于內(nèi)存映射區(qū)的大小,因此對于創(chuàng)建的新文件,可以使用文件截?cái)嗪瘮?shù)(ftruncate)來改變文件的大小和被復(fù)制的文件大小一樣,這樣子才能在映射一個(gè)和被復(fù)制的文件的映射區(qū)一樣大的內(nèi)存映射區(qū)。

      • 下面我將使用單進(jìn)程和多進(jìn)程兩種方式來進(jìn)行mmap文件復(fù)制

      單進(jìn)程mmap文件復(fù)制

      #include
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      /* 首先規(guī)定一下該命令的參數(shù) :
       * mycopy 源文件地址 目標(biāo)文件地址
       *
       * 可能需要的函數(shù):open\read\write\close
       * 基本流程:打開源文件,讀取內(nèi)容,寫到另一個(gè)文件,關(guān)閉文件
       * 核心方法:通過mmap(最快的進(jìn)程間通信方法) 
       * 如何獲取文件的大小:
       *
       */
      unsigned long get_file_byte_num(const char * filename)
      {
       FILE *fp = fopen(filename, "r");
       fseek(fp, 0, SEEK_END);
       return ftell(fp);
      }
      int main(int argc, char ** argv)
      {
       // 首先解析輸入的參數(shù)得到源文件和目標(biāo)文件
       if (argc < 3)
       {
        perror("參數(shù)輸入不足");
       }
       int slen = strlen(argv[1]); // 這個(gè)是源文件的名的長度
       int tlen = strlen(argv[2]); // 這個(gè)是目標(biāo)文件名的長度
       char *sname = (char *)malloc(sizeof(char)*(slen + 1));
       char *tname = (char*)malloc(sizeof(char)*(tlen + 1));
       strcpy(sname, argv[1]);
       strcpy(tname, argv[2]);
       // 打開目標(biāo)文件
       // 計(jì)算源文件的大小(字節(jié)數(shù))
       unsigned long byte_num = get_file_byte_num(sname);
       printf("文件的長度為%ld字節(jié)\n", byte_num);
       //--------建立 mmap 映射區(qū) --------------
       // 獲取被復(fù)制文件的文件描述符
       int fd = open(sname, O_RDWR|O_CREAT, 0644);
       int tfd = open(tname, O_RDWR|O_CREAT, 0644);
       ftruncate(tfd, byte_num);
      
       char *mem =(char*) mmap(NULL, byte_num, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
       if (mem == MAP_FAILED)
        perror("mmap err");
       char *tmem =(char*) mmap(NULL, byte_num, PROT_WRITE|PROT_READ, MAP_SHARED, tfd, 0);
       if (tmem == MAP_FAILED)
        perror("mmap err");
      
       close(fd); // 內(nèi)存映射區(qū)建立之后,就可以關(guān)閉文件描述符
       close(tfd);
      
       memcpy(tmem, mem, byte_num);
      
       // 回收子進(jìn)程,等待拷貝結(jié)束
       munmap(mem, byte_num);
       munmap(tmem, byte_num);
       free(sname);
       free(tname);

      多進(jìn)程mmap復(fù)制文件

      所謂的多進(jìn)程mmap復(fù)制文件,只是做了將復(fù)制的任務(wù)分給多個(gè)進(jìn)程去完成,核心思想不變。

      #include
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      #include 
      /* 首先規(guī)定一下該命令的參數(shù) :
      * mycopy 源文件地址 目標(biāo)文件地址
      *
      * 可能需要的函數(shù):open\read\write\close
      * 基本流程:打開源文件,讀取內(nèi)容,寫到另一個(gè)文件,關(guān)閉文件
      * 核心方法:通過mmap(最快的進(jìn)程間通信方法) 
      * 如何獲取文件的大小:
      *
      */
      // 獲取文件的字節(jié)數(shù)
      unsigned long get_file_byte_num(const char * filename)
      {
       FILE *fp = fopen(filename, "r");
       fseek(fp, 0, SEEK_END);
       return ftell(fp);
      }
      
      // sigchld信號(hào)處理函數(shù)
      void sigchld_handle(int a)
      {
       pid_t pid;
       while ((pid = waitpid(0,NULL, WNOHANG)) > 0)
       {
        printf("回收到一個(gè)子進(jìn)程%d\n", pid);
       }
      }
      
      int main(int argc, char ** argv)
      {
       // 首先解析輸入的參數(shù)得到源文件和目標(biāo)文件
       if (argc < 3)
       {
        perror("參數(shù)輸入不足");
       }
       int slen = strlen(argv[1]); // 這個(gè)是源文件的名的長度
       int tlen = strlen(argv[2]); // 這個(gè)是目標(biāo)文件名的長度
       char *sname = (char *)malloc(sizeof(char)*(slen + 1));
       char *tname = (char*)malloc(sizeof(char)*(tlen + 1));
       strcpy(sname, argv[1]);
       strcpy(tname, argv[2]);
       // 打開目標(biāo)文件
       FILE * tfp = fopen(tname, "w"); // 不存在則創(chuàng)建
       // 計(jì)算源文件的大小(字節(jié)數(shù))
       unsigned long byte_num = get_file_byte_num(sname);
       printf("文件的長度為%ld字節(jié)\n", byte_num);
       //--------建立 mmap 映射區(qū) --------------
       // 獲取被復(fù)制文件的文件描述符
       int fd = open(sname, O_RDWR|O_CREAT, 0644);
       int tfd = open(tname, O_RDWR|O_CREAT, 0644);
       ftruncate(tfd, byte_num); // 將tfd指向的文件的大小改變?yōu)閎yte_num
      
       char *mem =(char*) mmap(NULL, byte_num, PROT_WRITE|PROT_READ, MAP_SHARED, fd, 0);
       char * mem_tmp = mem; // 備份共享內(nèi)存入口地址
       if (mem == MAP_FAILED)
       perror("MAP_FAILED");
       char *tmem = (char*)mmap(NULL, byte_num, PROT_WRITE, MAP_SHARED,tfd, 0);
       char * tmem_tmp = tmem;
       if (tmem == MAP_FAILED)
       perror("mmap err");
      
       close(fd); // 內(nèi)存映射區(qū)建立之后,就可以關(guān)閉文件描述符
       close(tfd);
      
       // 父子進(jìn)程之間就可以通過這個(gè)mem指針進(jìn)行通信了
       // 規(guī)定進(jìn)程數(shù)量為5mZ const int num_proc = 5;
       // 根據(jù)進(jìn)程數(shù)量,計(jì)算每個(gè)進(jìn)程需要拷貝的字節(jié)數(shù),
       // 最后一個(gè)進(jìn)程拷貝剩余的字節(jié)數(shù)。
       const int num_proc = 5;
       const unsigned long each_proc_byte = byte_num/num_proc;
       // 由于可能無法整除,因此最后一個(gè)進(jìn)程,需要多復(fù)制一些
       const unsigned long last_proc_byte = byte_num - each_proc_byte*(num_proc - 1); 
      
       // 屏蔽sigchld信號(hào)的系統(tǒng)默認(rèn)處理方式
       sigset_t set;
       sigemptyset(&set); // 初始化一下set
       sigaddset(&set, SIGCHLD);
       sigprocmask(SIG_BLOCK, &set, NULL); // 屏蔽
      
       // 循環(huán)創(chuàng)建子進(jìn)程
      int i; 
      pid_t pid;
      for(i = 0; i < num_proc - 1; ++i)
      {
       if ((pid = fork())==-1)
       perror("fork error");
       if (pid == 0)
       break;
      }
      
       // -------具體的拷貝過程---------
       if (i == num_proc - 1) // 父進(jìn)程
       {
        // 設(shè)置信號(hào)捕捉和解除屏蔽
        struct sigaction act;
        act.sa_handler = sigchld_handle;
        sigemptyset(&act.sa_mask); // 處理期間不屏蔽其他信號(hào)
        sigaction(SIGCHLD, &act, NULL); // 啟動(dòng)信號(hào)捕獲
        sigprocmask(SIG_UNBLOCK, &set, NULL); // 解除SIGCHLD的屏蔽
      
        memcpy(tmem_tmp + each_proc_byte*i, mem_tmp + each_proc_byte*i, last_proc_byte); 
      
       }else
       {
        memcpy(tmem + each_proc_byte*i, mem_tmp + each_proc_byte*i, each_proc_byte);
       }
       //
       // 回收子進(jìn)程,等待拷貝結(jié)束
       //
      
        munmap(mem, byte_num);
        munmap(tmem, byte_num);
        free(sname);
        free(tname);
        return 0;
      }

      幾個(gè)問題

      1、主進(jìn)程什么時(shí)候進(jìn)行munmap才不會(huì)影響其他進(jìn)程使用mmap進(jìn)行復(fù)制。

      父子進(jìn)程之間的用戶空間遵循“讀時(shí)共享、寫時(shí)復(fù)制”的原則,mmap肯定是采用的用戶空間的內(nèi)存,因此我認(rèn)為最好的處理方法,就是每個(gè)進(jìn)程都進(jìn)行munmap。

      2、sleep()函數(shù)的注意點(diǎn):

      sleep在manpage上的原文解釋為:sleep() makes the calling process sleep until seconds seconds have elapsed or a signal arrives which is not ignored.

      也就是說,結(jié)束sleep的情況又兩種:1.休眠時(shí)間到。2.調(diào)用sleep的進(jìn)程收到一個(gè)信號(hào),且該信號(hào)未被屏蔽,在該信號(hào)處理完成后,理解結(jié)束sleep。

      關(guān)于利用mmap怎么對文件進(jìn)行復(fù)制就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。


      新聞標(biāo)題:利用mmap怎么對文件進(jìn)行復(fù)制
      本文來源:http://ef60e0e.cn/article/jhoehs.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        渭南市| 长海县| 闵行区| 上高县| 永康市| 隆林| 潢川县| 甘孜| 淮北市| 皋兰县| 仙游县| 资源县| 平远县| 乌兰浩特市| 濮阳市| 蒲江县| 甘谷县| 南溪县| 富顺县| 阿瓦提县| 荣昌县| 郑州市| 亚东县| 建阳市| 苏尼特左旗| 景泰县| 深水埗区| 忻州市| 乐至县| 琼海市| 措美县| 麦盖提县| 宁国市| 洪泽县| 兴山县| 奉化市| 长垣县| 永平县| 永兴县| 宁海县| 洮南市|