最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java  深入理解內(nèi)存映射文件原理

 更新時間:2016年11月30日 15:36:19   作者:楊龍飛的博客  
這篇文章主要介紹了java 深入理解內(nèi)存映射文件原理的相關(guān)資料,虛擬內(nèi)存與內(nèi)存映射文件的區(qū)別與聯(lián)系,內(nèi)存映射文件的原理和效率,需要的朋友可以參考下

內(nèi)存映射文件原理

首先說說這篇文章要解決什么問題?
1.虛擬內(nèi)存與內(nèi)存映射文件的區(qū)別與聯(lián)系.
2.內(nèi)存映射文件的原理.
3.內(nèi)存映射文件的效率.
4.傳統(tǒng)IO和內(nèi)存映射效率對比.

虛擬內(nèi)存與內(nèi)存映射文件的區(qū)別與聯(lián)系

 二者的聯(lián)系

虛擬內(nèi)存和內(nèi)存映射文件都是將一部分內(nèi)容加載到,另一部分放在磁盤上的一種機(jī)制,二者都是應(yīng)用程序動態(tài)性的基礎(chǔ),由于二者的虛擬性,對于用戶都是透明的.

虛擬內(nèi)存其實(shí)就是硬盤的一部分,是計算機(jī)RAM與硬盤的數(shù)據(jù)交換區(qū),因為實(shí)際的物理內(nèi)存可能遠(yuǎn)小于進(jìn)程的地址空間,這就需要把內(nèi)存中暫時不用到的數(shù)據(jù)放到硬盤上一個特殊的地方,當(dāng)請求的數(shù)據(jù)不在內(nèi)存中時,系統(tǒng)產(chǎn)生卻頁中斷,內(nèi)存管理器便將對應(yīng)的內(nèi)存頁重新從硬盤調(diào)入物理內(nèi)存。

內(nèi)存映射文件是由一個文件到一塊內(nèi)存的映射,使應(yīng)用程序可以通過內(nèi)存指針對磁盤上的文件進(jìn)行訪問,其過程就如同對加載了文件的內(nèi)存的訪問,因此內(nèi)存文件映射非常適合于用來管理大文件。

二者的區(qū)別

1.虛擬內(nèi)存使用硬盤只能是頁面文件,而內(nèi)存映射使用的磁盤部分可以是任何磁盤文件.

2.二者的架構(gòu)不同,或者是說應(yīng)用的場景不同,虛擬內(nèi)存是架構(gòu)在物理內(nèi)存之上,其引入是因為實(shí)際的物理內(nèi)存運(yùn)行程序所需的空間,即使現(xiàn)在計算機(jī)中的物理內(nèi)存越來越大,程序的尺寸也在增長。將所有運(yùn)行著的程序全部加載到內(nèi)存中不經(jīng)濟(jì)也非常不現(xiàn)實(shí)。內(nèi)存映射文件架構(gòu)在程序的地址空間之上,32位機(jī)地址空間只有4G,而某些大文件的尺寸可要要遠(yuǎn)超出這個值,因此,用地址空間中的某段應(yīng)用文件中的一部分可解決處理大文件的問題,在32中,使用內(nèi)存映射文件可以處理2的64次(64EB)大小的文件.原因內(nèi)存映射文件,除了處理大文件,還可用作進(jìn)程間通信。

內(nèi)存映射文件的原理

“映射”就是建立一種對應(yīng)關(guān)系,在這里主要是指硬盤上文件的位置與進(jìn)程邏輯地址空間中一塊相同區(qū)域之間一一對應(yīng),這種關(guān)系純屬是邏輯上的概念,物理上是不存在的,原因是進(jìn)程的邏輯地址空間本身就是不存在的,在內(nèi)存映射過程中,并沒有實(shí)際的數(shù)據(jù)拷貝,文件沒有被載入內(nèi)存,只是邏輯上放入了內(nèi)存,具體到代碼,就是建立并初始化了相關(guān)的數(shù)據(jù)結(jié)構(gòu),這個過程有系統(tǒng)調(diào)用mmap()實(shí)現(xiàn),所以映射的效率很高.

這里寫圖片描述
                     內(nèi)存映射原理
上面說到建立內(nèi)存映射沒有進(jìn)行實(shí)際的數(shù)據(jù)拷貝,那么進(jìn)行進(jìn)程又怎么能最終通過內(nèi)存操作訪問到硬盤上的文件呢?
看上圖:

1.調(diào)用mmap(),相當(dāng)于要給進(jìn)行內(nèi)存映射的文件分配了虛擬內(nèi)存,它會返回一個指針ptr,這個ptr所指向的是一個邏輯地址,要操作其中的數(shù)據(jù),必須通過MMU將邏輯地址轉(zhuǎn)換成物理地址,如圖1中過程2所示。

2.建立內(nèi)存映射并沒有實(shí)際拷貝數(shù)據(jù),這時,MMU在地址映射表中是無法找到與ptr相對應(yīng)的物理地址的,也就是MMU失敗,將產(chǎn)生一個缺頁中斷,缺 頁中斷的中斷響應(yīng)函數(shù)會在swap中尋找相對應(yīng)的頁面,如果找不到(也就是該文件從來沒有被讀入內(nèi)存的情況),則會通過mmap()建立的映射關(guān)系,從硬 盤上將文件讀取到物理內(nèi)存中,如圖1中過程3所示。

3.如果在拷貝數(shù)據(jù)時,發(fā)現(xiàn)物理內(nèi)存不夠用,則會通過虛擬內(nèi)存機(jī)制(swap)將暫時不用的物理頁面交換到硬盤上,如圖1中過程4所示。

內(nèi)存映射文件的效率

了解過內(nèi)存映射文件都知道,它比傳統(tǒng)的IO讀寫數(shù)據(jù)快很多,那么,它為什么會這么快,從代碼層面上來看,從硬盤上將文件讀入內(nèi)存,都是要經(jīng)過數(shù)據(jù)拷貝,并且數(shù)據(jù)拷貝操作是由文件系統(tǒng)和硬件驅(qū)動實(shí)現(xiàn)的,理論上來說,拷貝數(shù)據(jù)的效率是一 樣的。其實(shí),原因是read()是系統(tǒng)調(diào)用,其中進(jìn)行了數(shù)據(jù) 拷貝,它首先將文件內(nèi)容從硬盤拷貝到內(nèi)核空間的一個緩沖區(qū),如圖2中過程1,然后再將這些數(shù)據(jù)拷貝到用戶空間,如圖2中過程2,在這個過程中,實(shí)際上完成 了兩次數(shù)據(jù)拷貝 ;而mmap()也是系統(tǒng)調(diào)用,如前所述,mmap()中沒有進(jìn)行數(shù)據(jù)拷貝,真正的數(shù)據(jù)拷貝是在缺頁中斷處理時進(jìn)行的,由于mmap()將文件直接映射到用戶空間,所以中斷處理函數(shù)根據(jù)這個映射關(guān)系,直接將文件從硬盤拷貝到用戶空間,只進(jìn)行了 一次數(shù)據(jù)拷貝 。因此,內(nèi)存映射的效率要比read/write效率高。
這里寫圖片描述

read系統(tǒng)調(diào)用原理

傳統(tǒng)IO和內(nèi)存映射效率對比.

在這里,使用java傳統(tǒng)的IO,加緩沖區(qū)的IO,內(nèi)存映射分別讀取10M數(shù)據(jù).用時如下:

public class MapBufDelete {
  public static void main(String[] args) {
    try {
      FileInputStream fis=new FileInputStream("./largeFile.txt");
      int sum=0;
      int n;
      long t1=System.currentTimeMillis();
      try {
        while((n=fis.read())>=0){
          // 數(shù)據(jù)處理
        }
      } catch (IOException e) {
        e.printStackTrace();
      }
      long t=System.currentTimeMillis()-t1;
      System.out.println("傳統(tǒng)IOread文件,不使用緩沖區(qū),用時:"+t);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }

    try {
      FileInputStream fis=new FileInputStream("./largeFile.txt");
      BufferedInputStream bis=new BufferedInputStream(fis);
      int sum=0;
      int n;
      long t1=System.currentTimeMillis();
      try {
        while((n=bis.read())>=0){
         // 數(shù)據(jù)處理
        }
      } catch (IOException e) {

        e.printStackTrace();
      }
      long t=System.currentTimeMillis()-t1;
      System.out.println("傳統(tǒng)IOread文件,使用緩沖區(qū),用時:"+t);
    } catch (FileNotFoundException e) {
      e.printStackTrace();
    }

    MappedByteBuffer buffer=null;
    try {
      buffer=new RandomAccessFile("./largeFile.txt","rw").getChannel().map(FileChannel.MapMode.READ_WRITE, 0, 1253244);
      int sum=0;
      int n;
      long t1=System.currentTimeMillis();
      for(int i=0;i<1024*1024*10;i++){
        // 數(shù)據(jù)處理
      }
      long t=System.currentTimeMillis()-t1;
      System.out.println("內(nèi)存映射文件讀取文件,用時:"+t);
    } catch (FileNotFoundException e) {

      e.printStackTrace();
    } catch (IOException e) {
      e.printStackTrace();
    }finally {
    }

  }
}

運(yùn)行結(jié)果

傳統(tǒng)IOread文件,不使用緩沖區(qū),用時:4739

傳統(tǒng)IOread文件,使用緩沖區(qū),用時:59

內(nèi)存映射文件讀取文件,用時:11

最后,解釋一下,為什么使用緩沖區(qū)讀取文件會比不使用快:

原因是每次進(jìn)行IO操作,都要從用戶態(tài)陷入內(nèi)核態(tài),由內(nèi)核把數(shù)據(jù)從磁盤中讀到內(nèi)核緩沖區(qū),再由內(nèi)核緩沖區(qū)到用戶緩沖區(qū),如果沒有buffer,讀取都需要從用戶態(tài)到內(nèi)核態(tài)切換,而這種切換很耗時,所以,采用預(yù)讀,減少IO次數(shù),如果有buffer,根據(jù)局部性原理,就會一次多讀數(shù)據(jù),放到緩沖區(qū)中,減少了IO次數(shù).

感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!

相關(guān)文章

  • 基于RxJava框架實(shí)現(xiàn)獲取驗證碼的輔助類

    基于RxJava框架實(shí)現(xiàn)獲取驗證碼的輔助類

    這篇文章主要為大家詳細(xì)介紹了基于RxJava框架實(shí)現(xiàn)獲取驗證碼的輔助類,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-06-06
  • Android利用ViewPager實(shí)現(xiàn)用戶引導(dǎo)界面效果的方法

    Android利用ViewPager實(shí)現(xiàn)用戶引導(dǎo)界面效果的方法

    這篇文章主要介紹了Android利用ViewPager實(shí)現(xiàn)用戶引導(dǎo)界面效果的方法,結(jié)合實(shí)例形式詳細(xì)分析了Android軟件功能界面的初始化、view實(shí)例化、動畫功能實(shí)現(xiàn)與布局相關(guān)技巧,需要的朋友可以參考下
    2016-07-07
  • Android上下文菜單用法實(shí)例分析

    Android上下文菜單用法實(shí)例分析

    這篇文章主要介紹了Android上下文菜單用法,以完整實(shí)例形式分析了Android上下文菜單的定義、布局及功能實(shí)現(xiàn)技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-09-09
  • Android自定義組件跟隨自己手指主動畫圓

    Android自定義組件跟隨自己手指主動畫圓

    這篇文章主要為大家詳細(xì)介紹了Android自定義組件跟隨自己手指主動畫圓,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android實(shí)現(xiàn)登錄界面的注冊功能

    Android實(shí)現(xiàn)登錄界面的注冊功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)登錄界面的注冊功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Android實(shí)現(xiàn)文件資源管理器雛形

    Android實(shí)現(xiàn)文件資源管理器雛形

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)文件資源管理器雛形,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-03-03
  • Android高德地圖marker自定義彈框窗口

    Android高德地圖marker自定義彈框窗口

    這篇文章主要為大家詳細(xì)介紹了Android高德地圖marker自定義彈框窗口,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-04-04
  • android實(shí)現(xiàn)將位置信息寫入JPEG圖片文件

    android實(shí)現(xiàn)將位置信息寫入JPEG圖片文件

    下面小編就為大家?guī)硪黄猘ndroid實(shí)現(xiàn)將位置信息寫入JPEG圖片文件。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-03-03
  • Android獲取位置信息的方法

    Android獲取位置信息的方法

    這篇文章主要為大家詳細(xì)介紹了Android獲取位置信息的方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-05-05
  • Android仿IOS自定義AlertDialog提示框

    Android仿IOS自定義AlertDialog提示框

    本篇文章主要介紹了Android仿IOS自定義AlertDialog對話框,主要介紹了圓角AlertDialog對話框,具有一定的參考價值,有興趣的可以了解一下。
    2017-03-03

最新評論

珠海市| 定边县| 岳普湖县| 屯留县| 牙克石市| 南康市| 酒泉市| 桦甸市| 土默特左旗| 克拉玛依市| 赣榆县| 迁西县| 措美县| 江油市| 商河县| 富阳市| 宣武区| 咸阳市| 小金县| 襄城县| 石家庄市| 定结县| 富阳市| 囊谦县| 长宁县| 天祝| 诸城市| 甘孜| 炉霍县| 顺平县| 高唐县| 高要市| 行唐县| 建宁县| 饶平县| 景洪市| 汾西县| 珲春市| 潼南县| 惠水县| 银川市|