知識(shí)
不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價(jià)值,我們?cè)谧非笃湟曈X表現(xiàn)的同時(shí),更側(cè)重于功能的便捷,營銷的便利,運(yùn)營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實(shí)提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序?yàn)楹笃谏?jí)提供便捷的支持!
文件映射IO(mmap
發(fā)表時(shí)間:2020-10-19
發(fā)布人:葵宇科技
瀏覽次數(shù):40
本文介紹在POSIX情況應(yīng)用文件映射IO操作的辦法,文件映射IO又被稱為存儲(chǔ)映射IO,對(duì)于通俗文件而言,很多時(shí)刻它是高效的,它實(shí)際削減了數(shù)據(jù)的復(fù)制;同時(shí)它也可以用于特別的處所,用于過程之間的通信,共享內(nèi)存的一種方法。
我們可以或許把一個(gè)文件想象成一塊持續(xù)的數(shù)據(jù),大年夜純粹的數(shù)據(jù)角度來看,任何通俗文件都可以這么懂得。文件映射實(shí)際上是把文件的┞封塊數(shù)據(jù)與我們法度榜樣里的一塊內(nèi)存對(duì)應(yīng)上了,應(yīng)用我們操作這塊內(nèi)存的時(shí)刻,看上去現(xiàn)其實(shí)操作這個(gè)文件。這就是文件映射的概念。這個(gè)概念很巨大年夜,它直接避免了內(nèi)核與用戶之間的一層數(shù)據(jù)復(fù)制,所以很多時(shí)刻,它會(huì)比其它方法的文件操作更快一些,尤其對(duì)于通俗的磁盤文件而言更是如斯。
創(chuàng)建映射區(qū):mmap
我們經(jīng)由過程函數(shù)mmap來告訴操作體系把哪個(gè)文件映射哪塊內(nèi)存去,并且設(shè)置我們可能對(duì)這塊內(nèi)存的不克不及操作,就是對(duì)文件一樣。
#include<sys/mman.h>
void* mmap(void* addr, size_t len, int port, int flag, int filedes, off_t off)
返回值:成功返回被映射的內(nèi)存地址,掉敗返回MAP_FIALED
參數(shù) addr
這個(gè)只有在極少數(shù)情況下才不為0,這個(gè)參數(shù)告訴內(nèi)核應(yīng)用addr指定的值來竽暌鉤射指定文件。當(dāng)指定為0的時(shí)刻,告訴內(nèi)核返回什么地址內(nèi)其自身決定。除非異常懂得體系過程模式,或者對(duì)當(dāng)前情況異常懂得,不然的話手工指定則個(gè)值老是弗采取。
參數(shù) len
指定被映射的內(nèi)存區(qū)域的長度。
參數(shù) port
這個(gè)參數(shù)對(duì)應(yīng)open函數(shù)的權(quán)限位,我們可以指定為:PROT_READ,映射區(qū)可讀;PROT_WRITE,映射區(qū)可寫;PROT_EXEC,映射區(qū)可履行;PROT_NONE,映射區(qū)弗查拜訪。因?yàn)橹荒苡成湟呀?jīng)打開的文件,所以這個(gè)權(quán)限位不克不及超出open函數(shù)指定的權(quán)限,比如說袈溱open的時(shí)刻指定為只讀,那就不克不及在此時(shí)指定PORT_WRITE。
參數(shù) flag
這個(gè)參數(shù)指定了映射區(qū)的其它一些屬性,權(quán)限的屬性已經(jīng)在port中指定。這里可能存在的典范值有:MAP_FIXED,針對(duì)addr屬性,如不雅指定則個(gè)位,那么請(qǐng)求體系必須在指定的地址映射,這往往是弗采取的;MAP_SHARED,此標(biāo)記解釋指定映射區(qū)是共享的,意思就是說對(duì)內(nèi)存的操作與對(duì)文件的操作是相對(duì)應(yīng)的,它不克不及與MAP_PRIVATE標(biāo)記一向應(yīng)用,因?yàn)樗鼈儽磉_(dá)的意圖是相反的;MAP_PRIVATE,該標(biāo)記解釋映射區(qū)是私用的,此時(shí)被映射的內(nèi)存只能被當(dāng)前里程應(yīng)用,當(dāng)進(jìn)遲疑作的內(nèi)存將會(huì)產(chǎn)生原文件的一個(gè)副本。
MAP_FIXED //應(yīng)用指定的映射肇端地址,如不雅由start和len參數(shù)指定的內(nèi)存區(qū)重疊于現(xiàn)存的映射空間,重疊部分將會(huì)被丟棄。如不雅指定的肇端地址弗采取,操作將會(huì)掉敗。并且肇端地址必須落在頁的界線上。
MAP_SHARED //與其它所有映贍┞封個(gè)對(duì)象的過程共享映射空間。對(duì)共享區(qū)的寫入,相當(dāng)于輸出到文件。直到msync()或者munmap()被調(diào)用,文件實(shí)際上不會(huì)被更新。
MAP_PRIVATE //建立一個(gè)寫入時(shí)拷貝的私有映射。內(nèi)存區(qū)域的寫入不會(huì)影響到原文件。這個(gè)標(biāo)記和以上標(biāo)記是互斥的,只能應(yīng)用個(gè)一一個(gè)。
MAP_DENYWRITE //這個(gè)標(biāo)記被忽視。
MAP_EXECUTABLE //同上
MAP_NORESERVE //不要為這個(gè)映射保存交換空間。當(dāng)交換空間被保存,對(duì)映射區(qū)修改的可能會(huì)獲得包管。當(dāng)交換空間不被保存,同時(shí)內(nèi)存不足,對(duì)映射區(qū)的修改會(huì)引起段違例旌旗燈號(hào)。
MAP_LOCKED //鎖定映射區(qū)的頁面,大年夜而防止頁面被交換出內(nèi)存。
MAP_GROWSDOWN //用于客棧,告訴內(nèi)核VM體系,映射區(qū)可以向下擴(kuò)大。
MAP_ANONYMOUS //匿名映射,映射區(qū)不與任何文件接洽關(guān)系。
MAP_ANON //MAP_ANONYMOUS的別稱,不再被應(yīng)用。
MAP_FILE //兼容標(biāo)記,被忽視。
MAP_32BIT //將映射區(qū)放在過程地址空間的低2GB,MAP_FIXED指準(zhǔn)時(shí)會(huì)被忽視。當(dāng)前這個(gè)標(biāo)記只在x86-64平臺(tái)上獲得支撐。
MAP_POPULATE //為文件映射經(jīng)由過程預(yù)讀的方法預(yù)備好頁表。隨后對(duì)映射區(qū)的拜訪不會(huì)被頁違例壅塞。
MAP_NONBLOCK //僅和MAP_POPULATE一路應(yīng)用時(shí)才有意義。不履行預(yù)讀,只為已存在于內(nèi)存中的頁面建立頁表人口。
[img]http://img.blog.csdn.net/20150104160753744?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvYW5keWh1YWJpbmc=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
fd:有效的文件描述詞。一般是由open()函數(shù)返回,其值也可以設(shè)置為-1,此時(shí)須要指定flags參數(shù)中的MAP_ANON,注解進(jìn)行的是匿名映射。
off_toffset:被映射對(duì)象內(nèi)容的起點(diǎn)。
設(shè)置與同步映射區(qū):mprotect、msync
在mmap中我們有很多選項(xiàng)來控制最后獲得的映射區(qū)的一些屬性,在調(diào)用mmap函數(shù)之后,我仍然可以對(duì)個(gè)中的一些屬性進(jìn)行調(diào)劑,這經(jīng)由過程mprotect函數(shù)完成。此外在我們更新了內(nèi)存的內(nèi)容之后,這時(shí)可能想把這些內(nèi)容同步稻磁逄中的文件,這經(jīng)由過程msync函數(shù)來完成。
mprotect 函數(shù)可以更改一個(gè)已經(jīng)存在的映射區(qū)的拜訪權(quán)限。
#include<sys/mman.h>
int mprotect(void* addr, size_t len, int port)
返回值:成功返回0,掉敗返回-1
參數(shù) addr
這個(gè)參數(shù)是mmap返回的數(shù)值,此時(shí)它就是mprotect感化典范圍。
參數(shù) len
指定映射區(qū)的長度,它須要與mmap中指定雷同。
參數(shù) port
在膳綾擎我們已經(jīng)介紹了port的可能取值,mprotect功能就是把這個(gè)port指定的屬性施加于響應(yīng)的映射區(qū)上。
在映射區(qū)的內(nèi)容更新了,內(nèi)核并不是及時(shí)同步映射區(qū)與文件的,相反內(nèi)核很少主動(dòng)去同步,除非我們調(diào)用了函數(shù)msync或者封閉映射區(qū)(封閉映射區(qū)的時(shí)刻,也不是急速同步的)。
#include<sys/mman.h>
int msync(void* addr, size_t len, int flags)
返回:成功為0,掉敗為-1
參數(shù) addr與len
這兩個(gè)參數(shù)完全等同于mprotect中的響應(yīng)的參數(shù)。
參數(shù) flags
我們可以經(jīng)由過程指定flags為不合的值來請(qǐng)求內(nèi)核進(jìn)行的響應(yīng)的同步操作:MS_ASYNC,這實(shí)際上不請(qǐng)求內(nèi)核做什么,讓內(nèi)核自立去履行同步;MS_SYNC,請(qǐng)求內(nèi)核在返回之前把寫操作完成;MS_INVALIDATE,是一個(gè)可選的標(biāo)記,它告訴內(nèi)核丟棄沒有同步的部分。
解除映射區(qū):munmap
在過程尋出或者我們調(diào)用munmap的時(shí)刻,可以解除一個(gè)已經(jīng)存在的映射區(qū)。而封閉映射區(qū)對(duì)應(yīng)的文件是不會(huì)引起映射區(qū)的解除的。
#include<sys/mman.h>
int munmap(void* addr, size_t len)
返回:成功返回0,掉敗返回-1
munmap的參數(shù)含義是明顯而平常的,所以在這里不作描述,它們與之前的幾個(gè)含義完全雷同。
留意:旌旗燈號(hào)、過程、頁、文件
對(duì)映射區(qū)的操作可能引起兩個(gè)旌旗燈號(hào):SIGSEGV 與 SIGBUS。內(nèi)核會(huì)在進(jìn)查拜訪了弗采取的內(nèi)存時(shí)發(fā)送SIGSEGV旌旗燈號(hào)給過程,指導(dǎo)過程這一異常行動(dòng)。比如對(duì)一個(gè)只讀的映射區(qū)履行寫操作將收到這一旌旗燈號(hào)。在映射的時(shí)刻,如不雅文件本身的大年夜小沒有映射區(qū)的長度大年夜,那么在過程第一次拜訪跨越文件大年夜小的內(nèi)存區(qū)域的時(shí)刻,內(nèi)核會(huì)發(fā)送旌旗燈號(hào)SIGBUS旌旗燈號(hào),之后再次拜訪此區(qū)域之前的處所都可以正常應(yīng)用,但一旦再次跨越,兩樣也會(huì)收到旌旗燈號(hào)SIGBUS。所以一般情況都在映射之前調(diào)用諸如lseek+write如許的函數(shù)來改變文件現(xiàn)有大年夜小以合適映射區(qū)須要的長度。
過程調(diào)用fork一類函數(shù)的時(shí)刻子過程會(huì)復(fù)制父過程的地址空間,所以被映射的區(qū)域也會(huì)被映射,如斯映射區(qū)是父子過程共享的??梢越?jīng)由過程這種方法實(shí)現(xiàn)父子過程的內(nèi)存共享與通信。
大年夜內(nèi)核的角度,內(nèi)存是安頁來治理的,所以在映射的時(shí)刻內(nèi)核在指定大年夜小的基本上按頁鍔滔取整。頁的大年夜小是體系相干的,在POSIX情況下可以經(jīng)由過程調(diào)用sysconf函數(shù)來肯定。
只有在調(diào)用mmap時(shí)指定MAP_SHARED的情況文件內(nèi)容才會(huì)真正改變,不然文件內(nèi)容不會(huì)被同步,即使我們調(diào)用了msync或解除映射或過程終止。
相關(guān)案例查看更多
相關(guān)閱讀
- 云南省城鄉(xiāng)建設(shè)廳網(wǎng)站
- painter
- 網(wǎng)站建設(shè)招商
- 商標(biāo)注冊(cè)
- 云南省建設(shè)廳官方網(wǎng)站
- 云南網(wǎng)站建設(shè)哪家強(qiáng)
- 小程序商城
- 網(wǎng)站沒排名
- 云南花農(nóng)小程序
- web服務(wù)
- 云南小程序定制
- 云南網(wǎng)站建設(shè)公司排名
- 智慧農(nóng)貿(mào)市場
- 網(wǎng)站建設(shè)特性
- 云南etc微信小程序
- 百度人工排名
- 微分銷
- 云南建設(shè)廳官方網(wǎng)站
- 貴州小程序開發(fā)
- 保山小程序開發(fā)
- 云南小程序開發(fā)公司推薦
- 云南網(wǎng)站建設(shè)公司哪家好
- 云南網(wǎng)站設(shè)計(jì)
- 小程序開發(fā)平臺(tái)前十名
- 做網(wǎng)站
- 網(wǎng)頁制作
- 北京小程序制作
- Web開發(fā)框架
- 云南小程序公司
- 云南網(wǎng)站建設(shè)選