自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Mongodb源碼分析--內(nèi)存文件映射(MMAP)

數(shù)據(jù)庫 其他數(shù)據(jù)庫 MongoDB
在Mongodb中,其使用了操作系統(tǒng)底層提供的內(nèi)存映射機制,即MMAP。MMAP可以把磁盤文件的一部分或全部內(nèi)容直接映射到內(nèi)存,這樣文件中的信息位置就會在內(nèi)存中有對應(yīng)的地址空間,這時對文件的讀寫可以直接用指針來做,而不需要read/write函數(shù)了。同時操作系統(tǒng)會將數(shù)據(jù)刷新保存到磁盤上。

在Mongodb中,其使用了操作系統(tǒng)底層提供的內(nèi)存映射機制,即MMAP。MMAP可以把磁盤文件的一部分或全部內(nèi)容直接映射到內(nèi)存,這樣文件中的信息位置就會在內(nèi)存中有對應(yīng)的地址空間,這時對文件的讀寫可以直接用指針來做,而不需要read/write函數(shù)了。同時操作系統(tǒng)會將數(shù)據(jù)刷新保存到磁盤上。如下圖:

鑒于linux,window系統(tǒng)為mmap所提供的API大同小異(見下圖)。這里僅以mongodb對window系統(tǒng)的mmap調(diào)用機制為例,來說明一下其具體的實現(xiàn)方式,以及在mongodb啟動時,客戶端提交查詢和插入操作請求時mongodb的mmap執(zhí)行流程。

上面類圖中:

  1. MongoFile:定義了mongo文件對象常用操作,包括創(chuàng)建,關(guān)閉,設(shè)置名稱,flushAll,獲取MongoFile文件總尺寸等。
  2. MMF: 一個類型定義,其聲明:typedef MemoryMappedFile MMF;    
  3. MongoMMF:為了便于journaling/durability操作,對MemoryMappedFile進行了一些封裝(特別是對private views )

下面著重看一下windows提供的mmap的常用API:

  1. MapViewOfFile(): 把文件數(shù)據(jù)映射到進程的地址空間
  2. CreateFileMapping() : 創(chuàng)建一個新的文件映射內(nèi)核對象 
  3. FlushViewOfFile(): 強制系統(tǒng)將內(nèi)存中修改過的數(shù)據(jù)重新寫入磁盤映像,從而可以確保所有的數(shù)據(jù)更新能及時保存到磁盤
  4. CloseHandle(): 關(guān)閉文件映射對象和文件對象
  5. MapViewOfFileEx(): 將文件映射到指定的進程地址空間

參數(shù)說明:   

  1. MapViewOfFile(  
  2.     __in HANDLE hFileMappingObject,  /*hFileMappingObject是共享文件對象*/ 
  3.     __in DWORD dwDesiredAccess, /*dwDesiredAccess是文件共享屬性*/ 
  4.     __in DWORD dwFileOffsetHigh, /*dwFileOffsetHigh是文件共享區(qū)的偏移地址*/ 
  5.     __in DWORD dwFileOffsetLow, /*dwFileOffsetLow是文件共享區(qū)的偏移地址*/ 
  6.     __in SIZE_T dwNumberOfBytesToMap /*dwNumberOfBytesToMap是共享數(shù)據(jù)長度*/ 
  7.     );   
  1. //winbase.h  
  2.     CreateFileMappingW(  
  3.     __in      HANDLE hFile,   /*hFile是創(chuàng)建共享文件的句柄*/ 
  4.     __in_opt LPSECURITY_ATTRIBUTES lpFileMappingAttributes, /*lpFileMappingAttributes是文件共享的屬性*/ 
  5.     __in      DWORD flProtect,  /*flProtect是當(dāng)文件映射時讀寫文件的屬性*/ 
  6.     __in      DWORD dwMaximumSizeHigh, /*是文件共享的大小高位字節(jié)*/ 
  7.     __in      DWORD dwMaximumSizeLow, /*是文件共享的大小低位字節(jié)*/ 
  8.     __in_opt LPCWSTR lpName /*lpName是共享文件對象名稱*/ 
  9.     );  
  10.     #ifdef UNICODE  
  11.     #define CreateFileMapping  CreateFileMappingW  
  12.     #else  
  13.     #define CreateFileMapping  CreateFileMappingA  
  14.     #endif // !UNICODE  
  1. FlushViewOfFile(  
  2. __in LPCVOID lpBaseAddress, /*內(nèi)存映射文件中的視圖的一個字節(jié)的地址*/ 
  3. __in SIZE_T dwNumberOfBytesToFlush /*想要刷新的字節(jié)數(shù)*/ 
  4. );  
  1. MapViewOfFileEx(  
  2. __in HANDLE hFileMappingObject,  /*共享文件對象*/ 
  3. __in DWORD dwDesiredAccess, /*文件共享屬性*/ 
  4. __in DWORD dwFileOffsetHigh, /*文件共享區(qū)的偏移地址*/ 
  5. __in DWORD dwFileOffsetLow, /*文件共享區(qū)的偏移地址*/ 
  6. __in SIZE_T dwNumberOfBytesToMap /*共享數(shù)據(jù)長度*/ 
  7. __in_opt LPVOID lpBaseAddress /*指定映射文件映射對象的地址。如這個地址處沒有足夠的內(nèi)存空間,  
  8.                                 那么對MapViewOfFileEx的調(diào)用會失效*/ 
  9. ); 

下面我們看一下mongodb如何使用上述API,來實現(xiàn)windows環(huán)境下對mongofile進行mmap操作的.

  1. //mmap_win.cpp  
  2.     mutex mapViewMutex("mapView");//聲明mapView的互斥體(mutex)對象  
  3.    ourbitset writable;  
  4.  
  5.    /** unmapping 通知,以便清空 writable bits */ 
  6.    void MemoryMappedFile::clearWritableBits(void *p) {  
  7.        for( unsigned i = ((size_t)p)/ChunkSize; i <= (((size_t)p)+len)/ChunkSize; i++ ) {  
  8.            writable.clear(i);  
  9.            assert( !writable.get(i) );  
  10.        }  
  11.    }  
  12.  
  13.    MemoryMappedFile::MemoryMappedFile()  
  14.        : _flushMutex(new mutex("flushMutex")) {  
  15.        fd = 0;  
  16.        maphandle = 0;  
  17.        len = 0;  
  18.        created();  
  19.    }  
  20.    //關(guān)閉文件MemoryMappedFile  
  21.    void MemoryMappedFile::close() {  
  22.        for( vector<void*>::iterator i = views.begin(); i != views.end(); i++ ) {  
  23.            clearWritableBits(*i);  
  24.            UnmapViewOfFile(*i);  
  25.        }  
  26.        views.clear();  
  27.        if ( maphandle )  
  28.            CloseHandle(maphandle);//關(guān)閉文件映射對象和文件對象  
  29.        maphandle = 0;  
  30.        if ( fd )  
  31.            CloseHandle(fd);//關(guān)閉文件映射對象和文件對象  
  32.        fd = 0;  
  33.    }  
  34.  
  35.    unsigned long long mapped = 0;  
  36.    //創(chuàng)建只讀map  
  37.    void* MemoryMappedFile::createReadOnlyMap() {  
  38.        assert( maphandle );  
  39.        scoped_lock lk(mapViewMutex);  
  40.        void *p = MapViewOfFile(maphandle, FILE_MAP_READ, /*f ofs hi*/0, /*f ofs lo*/ 0, /*dwNumberOfBytesToMap 0 means to eof*/0);  
  41.        if ( p == 0 ) {  
  42.            DWORD e = GetLastError();  
  43.            log() << "FILE_MAP_READ MapViewOfFile failed " << filename() << " " << errnoWithDescription(e) << endl;  
  44.        }  
  45.        else {  
  46.            views.push_back(p);  
  47.        }  
  48.        return p;  
  49.    }  
  50.  
  51.    //創(chuàng)建指定名稱和大小的MapViewOfFile  
  52.    void* MemoryMappedFile::map(const char *filenameIn, unsigned long long &length, int options) {  
  53.        assert( fd == 0 && len == 0 ); // 僅能打開一次  
  54.        setFilename(filenameIn);  
  55.        /* big hack here: Babble uses db names with colons.  doesn't seem to work on windows.  temporary perhaps. */ 
  56.        char filename[256];  
  57.        strncpy(filename, filenameIn, 255);  
  58.        filename[255] = 0;  
  59.        {  
  60.            size_t len = strlen( filename );  
  61.            for ( size_t i=len-1; i>=0; i-- ) {  
  62.                if ( filename[i] == '/' ||  
  63.                        filename[i] == '\\' )  
  64.                    break;  
  65.  
  66.                if ( filename[i] == ':' )  
  67.                    filename[i] = '_';  
  68.            }  
  69.        }  
  70.  
  71.        updateLength( filename, length );//如果指定文件已存在,則用已存在的文件長度更新length值  
  72.        {  
  73.            DWORD createOptions = FILE_ATTRIBUTE_NORMAL;  
  74.            if ( options & SEQUENTIAL )  
  75.                createOptions |= FILE_FLAG_SEQUENTIAL_SCAN;//針對連續(xù)訪問對文件緩沖進行優(yōu)化選項  
  76.            DWORD rw = GENERIC_READ | GENERIC_WRITE;//普通讀/寫  
  77.            fd = CreateFile(//創(chuàng)建相關(guān)文件  
  78.                     toNativeString(filename).c_str(),//創(chuàng)建的文件名稱  
  79.                     rw, // desired access  
  80.                     FILE_SHARE_WRITE | FILE_SHARE_READ, // share mode  
  81.                     NULL, // security  
  82.                     OPEN_ALWAYS, // create disposition  
  83.                     createOptions , // flags  
  84.                     NULL); // hTempl  
  85.            if ( fd == INVALID_HANDLE_VALUE ) {  
  86.                DWORD e = GetLastError();  
  87.                log() << "Create/OpenFile failed " << filename << " errno:" << e << endl;  
  88.                return 0;  
  89.            }  
  90.        }  
  91.  
  92.        mapped += length;  
  93.        {  
  94.  
  95.           //采用“讀寫文件數(shù)據(jù)”方式的頁面保護屬性             
  96.  
  97.           DWORD flProtect = PAGE_READWRITE;  
  98.  
  99.            //創(chuàng)建一個文件映射內(nèi)核對象并告訴系統(tǒng)文件的尺寸以及訪問文件的方式  
  100.            maphandle = CreateFileMapping(fd, NULL, flProtect,  
  101.                                          length >> 32 /*maxsizehigh*/,  
  102.                                          (unsigned) length /*maxsizelow*/,  
  103.                                          NULL/*lpName*/);  
  104.            if ( maphandle == NULL ) {  
  105.  
  106.               // 先獲取操作信息, 因為下面的log()要刪除lasterror信息  
  107.                DWORD e = GetLastError();  
  108.                log() << "CreateFileMapping failed " << filename << ' ' << errnoWithDescription(e) << endl;  
  109.                close();  
  110.                return 0;  
  111.            }  
  112.        }  
  113.  
  114.        void *view = 0;  
  115.        {  
  116.            scoped_lock lk(mapViewMutex);  
  117.            DWORD access = (options&READONLY)? FILE_MAP_READ : FILE_MAP_ALL_ACCESS;  
  118.  
  119.            //把文件數(shù)據(jù)映射到進程的地址空間  
  120.            view = MapViewOfFile(maphandle, access, /*f ofs hi*/0, /*f ofs lo*/ 0, /*dwNumberOfBytesToMap 0 means to eof*/0);  
  121.        }  
  122.        if ( view == 0 ) {  
  123.            DWORD e = GetLastError();  
  124.            log() << "MapViewOfFile failed " << filename << " " << errnoWithDescription(e) << endl;  
  125.            close();  
  126.        }  
  127.        else {  
  128.            views.push_back(view);  
  129.        }  
  130.        len = length;  
  131.  
  132.        return view;  
  133.    }  
  134.  
  135.    class WindowsFlushable : public MemoryMappedFile::Flushable {  
  136.    public:  
  137.        WindowsFlushable( void * view , HANDLE fd , string filename , boost::shared_ptr<mutex> flushMutex )  
  138.            : _view(view) , _fd(fd) , _filename(filename) , _flushMutex(flushMutex)  
  139.        {}  
  140.  
  141.        void flush() {  
  142.            if (!_view || !_fd)  
  143.                return;  
  144.  
  145.            scoped_lock lk(*_flushMutex);  
  146.            // 強制系統(tǒng)將內(nèi)存中修改過的數(shù)據(jù)重新寫入磁盤映像,從而可以確保所有的數(shù)據(jù)更新能及時保存到磁盤。  
  147.            bool success = FlushViewOfFile(_view, 0 /*0表示全部mapping*/);  
  148.            if (!success) {  
  149.                int err = GetLastError();  
  150.                out() << "FlushViewOfFile failed " << err << " file: " << _filename << endl;  
  151.            }  
  152.  
  153.            success = FlushFileBuffers(_fd);//刷新內(nèi)部文件緩沖區(qū)的數(shù)據(jù)刷到磁盤上  
  154.            if (!success) {  
  155.                int err = GetLastError();  
  156.                out() << "FlushFileBuffers failed " << err << " file: " << _filename << endl;  
  157.            }  
  158.        }  
  159.  
  160.        void * _view;  
  161.        HANDLE _fd;  
  162.        string _filename;  
  163.        boost::shared_ptr<mutex> _flushMutex;  
  164.    };  
  165.    //是否進行異步的flush操作(該操作會將修改過的數(shù)據(jù)部分或全部重新寫入磁盤映像)  
  166.    void MemoryMappedFile::flush(bool sync) {  
  167.     uassert(13056, "Async flushing not supported on windows", sync);//windows系統(tǒng)不支持異步flush  
  168.        if( !views.empty() ) {  
  169.            WindowsFlushable f( views[0] , fd , filename() , _flushMutex);  
  170.            f.flush();  
  171.        }  
  172.    }  
  173.   //預(yù)先刷數(shù)據(jù)操作,該方法確保這個對象是可以執(zhí)行flush()操作,以便在調(diào)用該方法之后執(zhí)行flush操作.  
  174.   //參見mmap.cpp flushAll操作  
  175.   MemoryMappedFile::Flushable * MemoryMappedFile::prepareFlush() {  
  176.        return new WindowsFlushable( views.empty() ? 0 : views[0] , fd , filename() , _flushMutex );  
  177.    }  
  178.    void MemoryMappedFile::_lock() {}  
  179.    void MemoryMappedFile::_unlock() {} 

上面的代碼比較簡單,大家看一下注釋就可以了,下面看一下mmf對于上面的MemoryMappedFile類實現(xiàn)是如何封裝的,因為mmf會在journaling/durability這類場景下使用PrivateMap():    

  1.    //mongommf.cpp文件  
  2.     //構(gòu)造PrivateMap  
  3.     void* MemoryMappedFile::createPrivateMap() {  
  4.         assert( maphandle );  
  5.         scoped_lock lk(mapViewMutex);  
  6.         //void *p = mapaligned(maphandle, len);  
  7.         void *p = MapViewOfFile(maphandle, FILE_MAP_READ, 0, 0, 0);  
  8.         if ( p == 0 ) {  
  9.             DWORD e = GetLastError();  
  10.             log() << "createPrivateMap failed " << filename() << " " << errnoWithDescription(e) << endl;  
  11.         }  
  12.         else {  
  13.             clearWritableBits(p);  
  14.             views.push_back(p);  
  15.         }  
  16.         return p;  
  17.     }  
  18.     //重新映射PrivateView  
  19.     void* MemoryMappedFile::remapPrivateView(void *oldPrivateAddr) {  
  20.         dbMutex.assertWriteLocked(); // short window where we are unmapped so must be exclusive  
  21.  
  22.         // mapViewMutex確保在重新映射時獲得相同的地址  
  23.         scoped_lock lk(mapViewMutex);  
  24.         //清空 writable bits  
  25.         clearWritableBits(oldPrivateAddr);  
  26.         //從進程的地址空間(oldPrivateAddr)撤消文件數(shù)據(jù)的映像  
  27.         if( !UnmapViewOfFile(oldPrivateAddr) ) {  
  28.             DWORD e = GetLastError();  
  29.             log() << "UnMapViewOfFile failed " << filename() << ' ' << errnoWithDescription(e) << endl;  
  30.             assert(false);  
  31.         }  
  32.  
  33.         // 將文件映射到指定的進程地址空間  
  34.         void *p = MapViewOfFileEx(maphandle, FILE_MAP_READ, 0, 0,  
  35.                                   /*dwNumberOfBytesToMap 0 means to eof*//*len*/,  
  36.                                   oldPrivateAddr);  
  37.           
  38.         if ( p == 0 ) {  
  39.             DWORD e = GetLastError();  
  40.             log() << "MapViewOfFileEx failed " << filename() << " " << errnoWithDescription(e) << endl;  
  41.             assert(p);  
  42.         }  
  43.         assert(p == oldPrivateAddr);  
  44.         return p;  
  45.     }  
  46. #endif  
  47.     //重新映射PrivateView  
  48.     void MongoMMF::remapThePrivateView() {  
  49.         assert( cmdLine.dur );  
  50.  
  51.         // todo 1.9 : it turns out we require that we always remap to the same address.  
  52.         // so the remove / add isn't necessary and can be removed  
  53.         privateViews.remove(_view_private);  
  54.         _view_private = remapPrivateView(_view_private);  
  55.         privateViews.add(_view_private, this);  
  56.     }  
  57.     ......  
  58.  
  59.     //打開指定的文件并執(zhí)行mmap操作  
  60.     bool MongoMMF::open(string fname, bool sequentialHint) {  
  61.         setPath(fname);  
  62.         _view_write = mapWithOptions(fname.c_str(), sequentialHint ? SEQUENTIAL : 0);  
  63.         return finishOpening();  
  64.     }  
  65.     //創(chuàng)建指定名稱的文件并執(zhí)行mmap操作  
  66.     bool MongoMMF::create(string fname, unsigned long long& len, bool sequentialHint) {  
  67.         setPath(fname);  
  68.         _view_write = map(fname.c_str(), len, sequentialHint ? SEQUENTIAL : 0);  
  69.         return finishOpening();  
  70.     }  
  71.     //創(chuàng)建PrivateMap并加載到privateViews集合中  
  72.     bool MongoMMF::finishOpening() {  
  73.         if( _view_write ) {  
  74.             if( cmdLine.dur ) {  
  75.                 _view_private = createPrivateMap();  
  76.                 if( _view_private == 0 ) {  
  77.                     massert( 13636 , "createPrivateMap failed (look in log for error)" , false );  
  78.                 }  
  79.                 privateViews.add(_view_private, this); // note that testIntent builds use this, even though it points to view_write then...  
  80.             }  
  81.             else {  
  82.                 _view_private = _view_write;  
  83.             }  
  84.             return true;  
  85.         }  
  86.         return false;  
  87.     }  
  88.     ......  
  89.     //從privateViews集合中移除當(dāng)前 _view_private,并關(guān)閉文件映射對象和文件對象  
  90.     void MongoMMF::close() {  
  91.         {  
  92.             if( cmdLine.dur && _view_write/*actually was opened*/ ) {  
  93.                 if( debug )  
  94.                     log() << "closingFileNotication:" << filename() << endl;  
  95.                 dur::closingFileNotification();  
  96.             }  
  97.             privateViews.remove(_view_private);  
  98.         }  
  99.         _view_write = _view_private = 0;  
  100.         MemoryMappedFile::close();//關(guān)閉文件映射對象和文件對象  
  101.     } 

mongodb完成了上面的工具類的聲明定義之后,就會在前臺使用這些類了,下面通過插入數(shù)據(jù)操作(之前主要流程我已在這篇文章中有所描述)過程中,對上面類的使用來進行闡述.  

首先需要說明的是,如果是***在本地運行mongod,則不會在指定的數(shù)據(jù)庫目錄(dbpath 參數(shù))下生成數(shù)據(jù)庫文件,但如果有數(shù)據(jù)插入時,則會生成相應(yīng)文件,這里可以理解為生成文件的過程就是mmap的創(chuàng)建過程。
    
之前的文章中提到過,當(dāng)客戶端要插入記錄時,則系統(tǒng)會根據(jù)客戶端的操作枚舉信息來調(diào)用相應(yīng)的操作,這里它會執(zhí)行instance.cpp文件中的receivedInsert方法,并進而調(diào)用 pdfile.cpp 文件的 insert()函數(shù),而在該方法下有如下一段代碼:

  1. DiskLoc DataFileMgr::insert(const char *ns, const void *obuf, int len, bool god, const BSONElement &writeId, bool mayAddIndex) {  
  2. ......  
  3.       NamespaceDetails *d = nsdetails(ns);//獲取ns的詳細(xì)信息  
  4.       if ( d == 0 ) {  
  5.           addNewNamespaceToCatalog(ns);//向system catalog添加新的名空間,它會再次調(diào)用當(dāng)前insert()方法  
  6.           
  7.           // 創(chuàng)建***個數(shù)據(jù)庫文件,方法位于database.cpp  
  8.           cc().database()->allocExtent(ns, Extent::initialSize(len), false);  
  9. ......  

上面的allocExtent方法用于分配Extent要求的磁盤空間,其中Extent用于記錄多個record記錄信息,而record就是數(shù)據(jù)庫中的一條記錄。這里可以將Extent看成是一個數(shù)據(jù)集合,但與我們通常所理解的"數(shù)據(jù)表"(datatable)有所差異,因為在同一個namespace下可以有一個或多個extent(可以不連續(xù)),extent之間是一個雙向鏈表結(jié)構(gòu),其通過cursor進行向前(forward)或反轉(zhuǎn)(reverse)的訪問。有關(guān)這些內(nèi)容,參見我之前寫的這篇文章。  

言歸正傳,在上面的allocExtent方法中,會執(zhí)行pdfile.cpp中的如下方法:

  1. //pdfile.cpp  
  2.  Extent* MongoDataFile::createExtent(const char *ns, int approxSize, bool newCapped, int loops) {  
  3.      .....  
  4.      int ExtentSize = approxSize <= header()->unusedLength ? approxSize : header()->unusedLength;  
  5.      DiskLoc loc;  
  6.      if ( ExtentSize < Extent::minSize() ) {//判斷當(dāng)前ExtentSize的大小  
  7.          ......  
  8.          //addAFile方法位于 database.cpp  
  9.          return cc().database()->addAFile( 0, true )->createExtent(ns, approxSize, newCapped, loops+1);  
  10.      .....  
  11.  
  12.  }  

***在addAFile方法中,我們會看下如下代碼段:

  1. //database.cpp  
  2.    MongoDataFile* Database::addAFile( int sizeNeeded, bool preallocateNextFile ) {  
  3.        int n = (int) files.size();  
  4.        MongoDataFile *ret = getFile( n, sizeNeeded );//調(diào)用下面的getFile方法  
  5.        .....  
  6.    }  
  7.  
  8.    //database.cpp    
  9.    MongoDataFile* Database::getFile( int n, int sizeNeeded , bool preallocateOnly) {  
  10.        ......  
  11.        namespaceIndex.init();  
  12.        .....  
  13.    }  
  14.      
  15.    //namespace.cpp    
  16.    void NamespaceIndex::init() {  
  17.        ......  
  18.        unsigned long long len = 0;  
  19.        boost::filesystem::path nsPath = path();  
  20.        string pathString = nsPath.string();  
  21.        void *p = 0;  
  22.        if( MMF::exists(nsPath) ) {//使用本文前面提到的MMF類,判斷數(shù)據(jù)庫文件是否存在  
  23.            if( f.open(pathString, true) ) {//打開指定的文件并執(zhí)行mmap操作  
  24.                len = f.length();  
  25.                if ( len % (1024*1024) != 0 ) {  
  26.                    log() << "bad .ns file: " << pathString << endl;  
  27.                    uassert( 10079 ,  "bad .ns file length, cannot open database", len % (1024*1024) == 0 );  
  28.                }  
  29.                p = f.getView();//返回mapview  
  30.            }  
  31.        }  
  32.        else {//不存在  
  33.            // use lenForNewNsFiles, we are making a new database  
  34.            massert( 10343, "bad lenForNewNsFiles", lenForNewNsFiles >= 1024*1024 );  
  35.            maybeMkdir();//創(chuàng)建相應(yīng)目錄(如不存在)  
  36.            unsigned long long l = lenForNewNsFiles;  
  37.            if( f.create(pathString, l, true) ) {//創(chuàng)建指定名稱的文件并執(zhí)行mmap操作  
  38.                getDur().createdFile(pathString, l); // always a new file  
  39.                len = l;  
  40.                assert( len == lenForNewNsFiles );  
  41.                p = f.getView();//返回mapview  
  42.            }  
  43.        }  
  44.        ......  
  45.    } 

下面用一張時序圖來大體回顧一下這***程:

在創(chuàng)建了該數(shù)據(jù)庫文件及相應(yīng)mmap操作之后,下面再重新啟動mongod時,系統(tǒng)會通過構(gòu)造client類的上下文對象 (context)方法來最終調(diào)用namespaceIndex.init()方法,其時序圖如下,大家可以通過調(diào)試源碼來難證這***程:

好了,今天的內(nèi)容到這里就告一段落。

參考鏈接:

  1. http://www.cnblogs.com/daizhj/archive/2011/03/30/1999699.html
  2. http://en.wikipedia.org/wiki/Mmap
  3. http://linux.about.com/library/cmd/blcmdl2_mmap.htm
  4. http://msdn.microsoft.com/en-us/library/aa366761.aspx
  5. http://hi.baidu.com/%B2%A4%B2%CB%B1%F9%B1%F9/blog/item/f6e6fb2561c0136a35a80f70.html            

 原文鏈接:http://www.cnblogs.com/daizhj/archive/2011/04/25/mongos_mmap_source_code.html

【編輯推薦】

  1. 走進MongoDB的世界 展開MongoDB的學(xué)習(xí)之旅
  2. 淺析Mongodb源碼之游標(biāo)Cursor
  3. 野心勃勃的NoSQL新貴 MongoDB應(yīng)用實戰(zhàn)
  4. MongoDB與CouchDB全方位對比
  5. MongoDB1.8發(fā)布,分布式文檔數(shù)據(jù)庫

 

責(zé)任編輯:艾婧 來源: 博客園
相關(guān)推薦

2023-03-01 10:37:51

2021-11-11 05:00:02

JavaMmap內(nèi)存

2014-07-28 11:20:20

mmap虛擬映射Linux

2021-12-03 16:20:26

鴻蒙HarmonyOS應(yīng)用

2011-05-26 10:05:48

MongoDB

2011-05-26 16:18:51

Mongodb

2009-07-24 10:00:38

.NET 4.0內(nèi)存映

2011-08-16 09:34:34

Nginx

2011-04-29 13:40:37

MongoDBCommand

2012-06-20 14:16:36

Java內(nèi)存映射

2024-10-31 09:24:42

2015-11-16 11:22:05

Java對象內(nèi)存分配

2020-10-09 07:13:11

Linux系統(tǒng)編程mmap

2021-12-03 16:22:05

鴻蒙HarmonyOS應(yīng)用

2009-08-13 14:21:04

.NET內(nèi)存映射文件

2021-04-27 13:56:49

內(nèi)存.映射地址

2023-08-03 07:30:01

JavaNIO庫

2021-04-23 20:59:02

ThreadLocal內(nèi)存

2021-12-02 15:08:23

鴻蒙HarmonyOS應(yīng)用

2017-01-11 14:02:32

JVM源碼內(nèi)存
點贊
收藏

51CTO技術(shù)棧公眾號