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");
    }
    
}

 

posted @ 2016-04-17 17:57  YDDMAX  阅读(3304)  评论(0编辑  收藏  举报