设为首页 收藏本站
查看: 1548|回复: 0

[经验分享] Mongodb源码分析--内存文件映射(MMAP)

[复制链接]

尚未签到

发表于 2015-7-6 05:35:23 | 显示全部楼层 |阅读模式
在Mongodb中,其使用了操作系统底层提供的内存映射机制,即MMAP。MMAP可以把磁盘文件的一部分或全部内容直接映射到内存,这样文件中的信息位置就会在内存中有对应的地址空间,这时对文件的读写可以直接用指针来做,而不需要read/write函数了。同时操作系统会将数据刷新保存到磁盘上。如下图:
         鉴于linux,window系统为mmap所提供的API大同小异(见下图)。这里仅以mongodb对window系统的mmap调用机制为例,来说明一下其具体的实现方式,以及在mongodb启动时,客户端提交查询和插入操作请求时mongodb的mmap执行流程。
   
    上面类图中:
    MongoFile:定义了mongo文件对象常用操作,包括创建,关闭,设置名称,flushAll,获取MongoFile文件总尺寸等。
    MMF: 一个类型定义,其声明:typedef MemoryMappedFile MMF;   
    MongoMMF:为了便于journaling/durability操作,对MemoryMappedFile进行了一些封装(特别是对private views )
      
    下面着重看一下windows提供的mmap的常用API:
    MapViewOfFile(): 把文件数据映射到进程的地址空间
    CreateFileMapping() : 创建一个新的文件映射内核对象
    FlushViewOfFile(): 强制系统将内存中修改过的数据重新写入磁盘映像,从而可以确保所有的数据更新能及时保存到磁盘
    CloseHandle(): 关闭文件映射对象和文件对象
    MapViewOfFileEx(): 将文件映射到指定的进程地址空间
    参数说明:   



MapViewOfFile(
    __in HANDLE hFileMappingObject,  /*hFileMappingObject是共享文件对象*/
    __in DWORD dwDesiredAccess, /*dwDesiredAccess是文件共享属性*/
    __in DWORD dwFileOffsetHigh, /*dwFileOffsetHigh是文件共享区的偏移地址*/
    __in DWORD dwFileOffsetLow, /*dwFileOffsetLow是文件共享区的偏移地址*/
    __in SIZE_T dwNumberOfBytesToMap /*dwNumberOfBytesToMap是共享数据长度*/
    );
  



//winbase.h
    CreateFileMappingW(
    __in      HANDLE hFile,   /*hFile是创建共享文件的句柄*/
    __in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes, /*lpFileMappingAttributes是文件共享的属性*/
    __in      DWORD flProtect,  /*flProtect是当文件映射时读写文件的属性*/
    __in      DWORD dwMaximumSizeHigh, /*是文件共享的大小高位字节*/
    __in      DWORD dwMaximumSizeLow, /*是文件共享的大小低位字节*/
    __in_opt LPCWSTR lpName /*lpName是共享文件对象名称*/
    );
    #ifdef UNICODE
    #define CreateFileMapping  CreateFileMappingW
    #else
    #define CreateFileMapping  CreateFileMappingA
    #endif // !UNICODE  



    FlushViewOfFile(
    __in LPCVOID lpBaseAddress, /*内存映射文件中的视图的一个字节的地址*/
    __in SIZE_T dwNumberOfBytesToFlush /*想要刷新的字节数*/
    );  



    MapViewOfFileEx(
    __in HANDLE hFileMappingObject,  /*共享文件对象*/
    __in DWORD dwDesiredAccess, /*文件共享属性*/
    __in DWORD dwFileOffsetHigh, /*文件共享区的偏移地址*/
    __in DWORD dwFileOffsetLow, /*文件共享区的偏移地址*/
    __in SIZE_T dwNumberOfBytesToMap /*共享数据长度*/
    __in_opt LPVOID lpBaseAddress /*指定映射文件映射对象的地址。如这个地址处没有足够的内存空间,
                                    那么对MapViewOfFileEx的调用会失效*/
    );  
    下面我们看一下mongodb如何使用上述API,来实现windows环境下对mongofile进行mmap操作的.
   



//mmap_win.cpp
     mutex mapViewMutex("mapView");//声明mapView的互斥体(mutex)对象
    ourbitset writable;
    /** unmapping 通知,以便清空 writable bits */
    void MemoryMappedFile::clearWritableBits(void *p) {
        for( unsigned i = ((size_t)p)/ChunkSize; i createExtent(ns, approxSize, newCapped, loops+1);
        .....
    }
  
  最后在addAFile方法中,我们会看下如下代码段:
   



//database.cpp
    MongoDataFile* Database::addAFile( int sizeNeeded, bool preallocateNextFile ) {
        int n = (int) files.size();
        MongoDataFile *ret = getFile( n, sizeNeeded );//调用下面的getFile方法
        .....
    }
    //database.cpp  
    MongoDataFile* Database::getFile( int n, int sizeNeeded , bool preallocateOnly) {
        ......
        namespaceIndex.init();
        .....
    }
   
    //namespace.cpp  
    void NamespaceIndex::init() {
        ......
        unsigned long long len = 0;
        boost::filesystem::path nsPath = path();
        string pathString = nsPath.string();
        void *p = 0;
        if( MMF::exists(nsPath) ) {//使用本文前面提到的MMF类,判断数据库文件是否存在
            if( f.open(pathString, true) ) {//打开指定的文件并执行mmap操作
                len = f.length();
                if ( len % (1024*1024) != 0 ) {
                    log()

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-83469-1-1.html 上篇帖子: 第三节 MongoDB下samus源码初探 下篇帖子: 第一节: MongoDb环境部署
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表