mmap和MappedByteBuffer


 1、MappedByteBuffer是DirectByteBuffer的子類

 2、MappedByteBuffer使用的是mmap技術。MappedByteBuffer將文件映射為內存,也可能會被存儲在虛擬內存里面,訪問的時候通過缺頁機制調進內存。

3、mmap可以實現兩個進程之間共享數據 http://kenby.iteye.com/blog/1164700

4、mmap原理   http://blog.chinaunix.net/uid-26669729-id-3077015.html

5、MappedByteBuffer有一個文件釋放問題,文件是在full gc的時候才會關閉   http://langgufu.iteye.com/blog/2107023

6、MappedByteBuffer能優化隨機讀(因為實際上會在內存里存放大量的頁/塊)

 

 

metaq在文件讀寫操作上做了一定的優化,使用內存映射的方式完成讀寫,替代了傳統的IO操作,從而大大的減少了文件讀寫系統調用的次數,提升了IO的性能。

傳統的文件訪問:

  • 系統調用打開文件,獲取文件描述符
  • 使用read write 系統調用進行IO
  • 系統調用關閉文件

這種方式是非常低效的, 每一次I/O操作都需要一次系統調用。 另外, 如果若干個進程訪問同一個文件, 每個進程都要在自己的地址空間維護一個副本, 浪費了內存空間

內存映射的方式:

  • 打開文件,得到文件描述符。
  • 獲取文件大小
  • 把文件映射成虛擬內存(mmap)
  • 通過對內存的讀寫來實現對文件的讀寫(memset或memcpy)
  • 卸載映射
  • 關閉文件

首先建立好虛擬內存和磁盤文件之間的映射(mmap系統調用),當進程訪問頁面時產生一個缺頁中斷,內核將頁面讀入內存(也就是說把磁盤上的文件拷貝到內存中),並且更新頁表指向該頁面。
所有進程共享同一物理內存,物理內存中可以只存儲一份數據,不同的進程只需要把自己的虛擬內存映射過去就可以了,這種方式非常方便於同一副本的共享,節省內存。
經過內存映射之后,文件內的數據就可以用內存讀/寫指令來訪問,而不是用Read和Write這樣的I/O系統函數,從而提高了文件存取速度。

package com.ydd.study.hello.mmap;
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
/**
 * 內存映射文件
 * @author yunzhu.ydd
 *
 */
public class MapedFile {
    private   final String FILE_NAME = "D://mapedFile.txt";
    private   final long fileSize = 1024 * 1024;// 1M
    private FileChannel fileChannel;
    private MappedByteBuffer mappedByteBuffer;
    private File file;
    public  MapedFile() throws IOException {
        this.file = new File(FILE_NAME);
        this.fileChannel = new RandomAccessFile(this.FILE_NAME, "rw")
                .getChannel();
        //產生一定大小的文件,byte默認都為0。也就是說文件的byte都被初始化為0了
        this.mappedByteBuffer = this.fileChannel.map(MapMode.READ_WRITE, 0,
                fileSize);
    }
    /**
     * 寫
     * @param str
     */
    public void write(String str)
    {
        mappedByteBuffer.put(str.getBytes());
    }
    /**
     * 讀文件
     */
    public void getAll()
    {
        System.out.println("capacity:"+mappedByteBuffer.capacity());
       for(int i=0;i<mappedByteBuffer.capacity();i++)
       {
         char c=(char)mappedByteBuffer.get(i);    
         if(c!=' '&&c!=0)
            System.out.print(c);     
       }    
       System.out.println();
    }
    /**
     * 通過MappedByteBuffer操作文件
     * @throws IOException
     */
    public void test_寫和讀() throws IOException
    {
        System.out.println("capacity:"+mappedByteBuffer.capacity());
        write("hello world");
        getAll();
        fileChannel.close();            
    }
    /**
     * MappedByteBuffer.slice()生成的是DirectByteBuffer,對該buffer寫操作會被直接寫到文件里面
     * @param str
     * @throws IOException
     */
    public void test_slic_寫和讀(String str) throws IOException
    {
        ByteBuffer buffer=mappedByteBuffer.slice();
        buffer.put(str.getBytes());
       System.out.println("mappedByteBuffer.clice產生的buffer類型為:"+buffer.getClass());
        getAll();
        fileChannel.close();    
        
        
    }
    public static void main(String[]a) throws IOException
    {
        MapedFile mappedFile=new MapedFile();
        //mappedFile. test_寫和讀();
        mappedFile.test_slic_寫和讀("hahahahahah");
    }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM