c++ mmap写入速度_Linux系统编程_用mmap+数组的方式修改数据文件
正文開始前,先聊點非技術(shù)的東西,推薦2本生動有趣的書:
- 《經(jīng)濟(jì)學(xué)原理 宏觀經(jīng)濟(jì)學(xué)》,曼昆,豆瓣評分9.3,4945人評價
- 《經(jīng)濟(jì)學(xué)原理 微觀經(jīng)濟(jì)學(xué)》,曼昆,豆瓣評分9.6,1879人評價
我想看這兩本書原因是:Joel on Software 在一篇 給計算機(jī)系學(xué)生 的忠告文章里說,畢業(yè)之前你一定要修一門經(jīng)濟(jì)學(xué)課程,Joel( stackoverflow 的創(chuàng)始人 ) 的話在我心里有很重的分量,我愿意接受他的建議,甚至認(rèn)為自己 應(yīng)該在高中時 就閱讀上面2本書。
這兩本書在豆瓣上的評價極高:
一看到《經(jīng)濟(jì)學(xué)原理》這樣的書名,我會立即把它歸為異次元一類,碰都不會去碰,別說讀它了,自從大學(xué)畢業(yè)后,對于任何此類教科書,我會毫不客氣地說,滾!
這種情緒的對立既包含了對中國教育制度的控訴,又體現(xiàn)了對死讀書無法改變命運的殘酷現(xiàn)實的無奈。
工作約7到8年后,自我體會到和社會的逐漸脫節(jié),這里不止是因為工作環(huán)境的隔離性和社交圈的狹窄,還有自身知識量的乏饋,光是義務(wù)教育和本科教育所建立的知識結(jié)構(gòu)顯然已經(jīng)無法支撐起我的求知欲所對應(yīng)的飛速發(fā)展的社會萬物,可是學(xué)習(xí)從何開始呢?
話說到這里,志同道合的人應(yīng)該知道怎么做了,我就不再講廢話了,下面回歸到技術(shù)上。
以下是正文:
一、背景知識
mmap()系統(tǒng)調(diào)用在調(diào)用進(jìn)程的虛擬地址空間中創(chuàng)建一個新內(nèi)存映射( memory mappings ),映射分為兩種:
文件映射( File mapping ):文件映射將一個文件的一部分直接映射到調(diào)用進(jìn)程的虛擬內(nèi)存中。一旦一個文件被映射之后就可以通過在相應(yīng)的內(nèi)存區(qū)域中操作字節(jié)來訪問文件內(nèi)容了。映射的分頁會在需要的時候從文件中(自動)加載。這種映射也被稱為基于文件的映射( file-based mapping )或內(nèi)存映射文件( memory-mapped file )。
匿名映射( Anonymous mapping ):匿名映射沒有對應(yīng)的文件,這種映射的分頁會被初始化為0。
我們可以使某個磁盤文件的內(nèi)容看起來就像是內(nèi)存中的一個數(shù)組。如果文件的內(nèi)容是由讀多條 C 語言結(jié)構(gòu)體描述的記錄構(gòu)成的話,你就可以通過訪問結(jié)構(gòu)體數(shù)組來更新文件的內(nèi)容了。
1. 創(chuàng)建映射: mmap()
mmap()系統(tǒng)調(diào)用在調(diào)用進(jìn)程的虛擬地址空間中創(chuàng)建一個新映射,如果是文件映射的話,是通過文件描述符和文件關(guān)聯(lián)在一起:
#include?void?*mmap(void?*addr,?size_t?length,?int?prot,?int?flags,?int?fd,?off_t?offset);
成功時 mmap() 會返回新映射的起始地址。發(fā)生錯誤時 mmap( )會返回 MAP_FAILED。
參數(shù):
addr,用去指定內(nèi)存區(qū)域的起始地址,為了可移植性,一般設(shè)為 NULL, 表示由系統(tǒng)自動決定內(nèi)存區(qū)域的起始地址。不管采用何種方式,內(nèi)核會選擇一個不與任何既有映射沖突的地址。
len, 映射區(qū)域的長度。
prot,映射區(qū)域的訪問權(quán)限,可選項包括 READ/WRITE/EXEC/NONE。
flags, 映射區(qū)域的可見性:
- 私有映射(MAP_PRIVATE):在映射內(nèi)容上發(fā)生的變更對其他進(jìn)程不可見,對于文件映射來講,變更將不會在底層文件上發(fā)生。
- 共享映射(MAP_SHARED):在映射內(nèi)容上發(fā)生的變更對所有共享同一個映射的其他進(jìn)程都可見,對于文件映射來講,變更將會發(fā)生在底層的文件上。
fd, 被映射的文件的文件描述符。
offset, 從該偏移位置開始映射。
更多知識點:
在打開描述符fd引用的文件時必須要具備與prot和flags參數(shù)值匹配的權(quán)限。
offset參數(shù)指定了從文件區(qū)域中的哪個字節(jié)開始映射,它必須是系統(tǒng)分頁大小的倍數(shù)。
一旦mmap()被調(diào)用之后就能夠關(guān)閉文件描述符了,而不會對映射產(chǎn)生任何影響。
在Linux上,一個文件映射的分頁會在首次被訪問時被映射進(jìn)內(nèi)存。
除了普通的磁盤文件,使用 mmap() 還能夠映射各種真實和虛擬設(shè)備的內(nèi)容,如硬盤、光盤以及/dev/mem。
2. 同步映射區(qū)域:msync()
msync() 系統(tǒng)調(diào)用讓應(yīng)用程序能夠顯式地 在某種程度上 控制何時完成共享映射與映射文件之間的同步。
$?man?msyncSYNOPSIS
????#include?
???????int?msync(void?*addr,?size_t?length,?int?flags);
DESCRIPTION
???????msync()??flushes??changes?made?to?the?in-core?copy?of?a?file?that?was?mapped?into?memory?using?mmap(2)?back?to?the?filesystem.
參數(shù):
addr和length參數(shù)指定了需同步的內(nèi)存區(qū)域的起始地址和大小。
flags 的可取值:
- MS_SYNC,執(zhí)行一個同步的文件寫入。會阻塞直到內(nèi)存區(qū)域中所有被修改過的分頁被寫入到磁盤為止。
- MS_ASYNC,執(zhí)行一個異步的文件寫入,會立即返回。內(nèi)存區(qū)域中被修改過的分頁會在后面某個時刻被寫入磁盤并立即對在相應(yīng)文件區(qū)域中執(zhí)行 read() 的其他進(jìn)程可見。
- MS_INVALIDATE,使映射數(shù)據(jù)的緩存副本失效。其結(jié)果是其他進(jìn)程對文件做出的所有更新將會在內(nèi)存區(qū)域中可見。
更多知識點:
如果映射是私有的,那么不修改被映射的文件。
與其他內(nèi)存映射函數(shù)一樣,地址必須與頁邊界對齊。
MS_ASYNC 不保證何時寫入,因為在后臺運行的 IO elevator 算法試圖通過合并和排序?qū)懭雭碜畲蟪潭鹊靥岣咝?#xff0c;以最大程度地提高 IO 的吞吐量。
二、演示 demo
1. 分解代碼
定義數(shù)據(jù)類型:
typedef?struct?{????int?integer;
????char?string[24];
}?RECORD;
構(gòu)造數(shù)據(jù)文件 records.dat:
fp?=?fopen("records.dat","w+");for(i=0;?i????record.integer?=?i;
????sprintf(record.string,"RECORD-%d",i);
????fwrite(&record,sizeof(record),1,fp);
}
映射文件 records.dat:
f?=?open("records.dat",O_RDWR);mapped?=?(RECORD?*)mmap(0,?NRECORDS*sizeof(record),?
????????????????????????PROT_READ|PROT_WRITE,?MAP_SHARED,?f,?0);
通過結(jié)構(gòu)體數(shù)組修改數(shù)據(jù)( RECORD-43->RECORD-243 ):
mapped[43].integer?=?243;sprintf(mapped[43].string,"RECORD-%d",mapped[43].integer);
msync((void?*)mapped,?NRECORDS*sizeof(record),?MS_ASYNC);
清理現(xiàn)場:
munmap((void?*)mapped,?NRECORDS*sizeof(record));close(f);
2. 運行效果
$?gcc?mmap.c?-o?mmap$?./mmap
$?ls
mmap??mmap.c??records.dat
$?strings?records.dat
RECORD-0
RECORD-1
RECORD-2
...
RECORD-42
RECORD-243
RECORD-44
...
可以看到:RECORD-43 被成功修改為 RECORD-243。
演示的 demo 就這么簡單,卻需要如此多的背景知識,甚至還有大量的細(xì)節(jié)沒在文中披露,有需要時再深入講解吧。
三、相關(guān)參考
- 《Linux/Unix 系統(tǒng)編程手冊-第49章 內(nèi)存映射》
- 《Linux程序設(shè)計-第3章 文件操作》
- 《Unix 環(huán)境高級編程-第14章節(jié) 14.8-存儲映射I/O》
- LWN: R.I.P. pdflush
- Stack Overflow: msync(MS_ASYNC) flush order
你和我各有一個蘋果,如果我們交換蘋果的話,我們還是只有一個蘋果。但當(dāng)你和我各有一個想法,我們交換想法的話,我們就都有兩個想法了。如果你也對 嵌入式系統(tǒng)和開源軟件 感興趣,并且想和更多人互相交流學(xué)習(xí)的話,請關(guān)注我的公眾號:嵌入式系統(tǒng)磚家,一起來學(xué)習(xí)吧,關(guān)注或轉(zhuǎn)發(fā)都是是對作者最大的支持,謝謝大家,祝工作順利~
總結(jié)
以上是生活随笔為你收集整理的c++ mmap写入速度_Linux系统编程_用mmap+数组的方式修改数据文件的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: access考试素材_NCRE考试当天常
- 下一篇: python生成excel模板_使用py