微信MMKV原始碼分析 二 mmap對映

2021-09-11 14:56:44 字數 2630 閱讀 8566

系列文章:

void mmkv::loadfromfile

() m_metainfo.read(m_metafile.getmemory());

/* o_rdwr:讀、寫開啟

* o_creat:若此檔案不存在則建立它。使用此選擇項時,需同時說明第三個引數mode,用其說明該新檔案的訪問許可權位。

* s_irwxu:模式標誌:由使用者讀,寫,執行。

*/m_fd = open(m_path.c_str(), o_rdwr | o_creat, s_irwxu);

if (m_fd < 0) else ;

// 讀取檔案的大小

if (fstat(m_fd, &st) != -1)

// 對齊操作,mmap的使用要求

// round up to (n * pagesize)

if (m_size < default_mmap_size || (m_size % default_mmap_size != 0))

zerofillfile(m_fd, oldsize, m_size - oldsize);

}// mmkv的核心之一,使用mmap函式的map_shared來實現檔案和記憶體形成對映,只要修改記憶體的資料,這個函式會自動的幫我們寫到檔案裡,非常好用。

m_ptr = (char *) mmap(nullptr, m_size, prot_read | prot_write, map_shared, m_fd, 0);

if (m_ptr == map_failed) else

// 將記憶體的資料反序列化到map裡,m_dic是個map

m_dic = minipbcoder::decodemap(inputbuffer);

m_output = new codedoutputdata(m_ptr + fixed32size + m_actualsize,

m_size - fixed32size - m_actualsize);

loaded = true;}}

}if (!loaded)

m_output = new codedoutputdata(m_ptr + fixed32size, m_size - fixed32size);

recaculatecrcdigest();

}mmkvinfo("loaded [%s] with %zu values", m_mmapid.c_str(), m_dic.size());}}

if (!isfilevalid())

m_needloadfromfile = false;

}複製**

mmap函式是mmkv的乾貨之一了,如果沒有這個函式的存在,或許就沒有今天的mmkv了,下面說下這個函式的引數和使用方法。

mmap (一種記憶體對映檔案的方法)

mmap將乙個檔案或者其它物件對映進記憶體。檔案被對映到多個頁上,如果檔案的大小不是所有頁的大小之和,最後乙個頁不被使用的空間將會清零。mmap在使用者空間對映呼叫系統中作用很大。

標頭檔案

函式原型

void* mmap(void* start,size_t length,int prot,int flags,int fd,off_t offset);

length:對映區的長度。傳入檔案對齊後的大小m_size。

prot:期望的記憶體保護標誌,不能與檔案的開啟模式衝突。設定可讀可寫。

flags:指定對映物件的型別,對映選項和對映頁是否可以共享。設定map_shared表示可程序共享,mmkv之所以可以實現跨程序使用,這裡是關鍵。

fd:有效的檔案描述詞。用上面所開啟的m_fd。

off_toffset:被對映物件內容的起點。從頭開始,比較好理解。

在跨程序讀寫的時候,程序a修改了乙個資料,程序b去讀的時候,就會校驗記憶體的資料和檔案的資料,一旦不相同,就說明有了跨程序的操作,這個時候就需要記憶體重組,清空原有資料,重新讀最新的檔案對映到記憶體中。

void mmkv::checkloaddata

() if (!m_isinterprocess)

// todo: atomic lock m_metafile?

mmkvmetainfo metainfo;

// 讀取檔案的狀態

metainfo.read(m_metafile.getmemory());

// 對比檔案和記憶體的讀寫操作次數,次數不一樣,說明跨程序操作了,清空下原資料,再載入新資料

if (m_metainfo.m_sequence != metainfo.m_sequence)

// 比較下crc校驗碼

else

if (m_metainfo.m_crcdigest != metainfo.m_crcdigest) else ;

if (fstat(m_fd, &st) != -1)

}if (m_size != filesize) else

}}複製**

記憶體重組涉及到跨程序操作,跨程序的原理在後續文章再詳細講解。

關於crc32校驗,看《crc32加密演算法原理》

如果本文對您有用的話,記得點乙個贊哦!

PHP實現微信退款的分析與原始碼實現

原文 需要注意的事項 4.錯誤碼參照 如下 2.錯誤碼參照 header content type text html charset utf 8 mchid xx apikey xx 帳戶設定 安全設定 api安全 api金鑰 設定api金鑰 orderno wxorderno totalfee ...

PHP實現微信退款的分析與原始碼實現

原文 需要注意的事項 4.錯誤碼參照 如下 2.錯誤碼參照 header content type text html charset utf 8 mchid xx apikey xx 帳戶設定 安全設定 api安全 api金鑰 設定api金鑰 orderno wxorderno totalfee ...

二 LinkedList原始碼分析

二 linkedlist原始碼分析 上篇看了下arraylist原始碼,這篇記錄下linkedlist原始碼分析 linkedlist 繼承 abstractsequentiallist 提供了對元素順序訪問的抽象 linkedlist 實現 deque介面,底層構成雙向鍊錶結構 linkedlis...