Android mmap 文件映射到內存介紹

本文連接: Android mmap 文件映射到內存介紹android

Android開發中,咱們可能須要記錄一些文件。例如記錄log文件。若是使用流來寫文件,頻繁操做文件io可能會引發性能問題。 爲了下降寫文件的頻率,咱們可能會採用緩存必定數量的log,再一次性把它們寫到文件中。若是app異常退出,咱們有可能會丟失內存中的log信息。 那麼有什麼比較穩妥的寫文件方式,既能下降io,又能儘量地保證數據被寫入文件呢?緩存

mmap簡介

mmap概念

mmap是一種內存映射文件的方法,即將一個文件或者其它對象映射到進程的地址空間,實現文件磁盤地址和進程虛擬地址空間中一段虛擬地址的一一對映關係。app

特色:實現這樣的映射關係後,進程就能夠採用指針的方式讀寫操做這一段內存,而系統會自動回寫髒頁面到對應的文件磁盤上,即完成了對文件的操做而沒必要再調用read,write等系統調用函數。相反,內核空間對這段區域的修改也直接反映用戶空間,從而能夠實現不一樣進程間的文件共享。以下圖所示:dom

mmap簡介

mmap內存映射原理

mmap內存映射的實現過程,總的來講能夠分爲三個階段:函數

應用進程啓動映射,在進程的虛擬地址空間中,尋找一段空閒的知足要求的連續的虛擬地址做爲映射區域; 調用系統函數mmap,實現文件物理地址和進程虛擬地址的一一映射; 應用進程對映射區域訪問,引起缺頁異常,實現文件內容到物理內存(主存)的拷貝。工具

mmap優缺點

只有一次數據拷貝:當發生缺頁異常時,直接將數據從磁盤拷貝到進程的用戶空間,跳過了頁緩存。 實現了用戶空間和內核空間的高效交互方式:兩空間的各自修改操做能夠直接反映在映射的區域內,從而被對方空間及時捕捉。 提供進程間共享內存及相互通訊的方式。post

無論是父子進程仍是無親緣關係的進程,均可以將自身用戶空間映射到同一個文件或匿名映射到同一片區域。從而經過各自對映射區域的改動,達到進程間通訊和進程間共享的目的。性能

同時,若是進程A和進程B都映射了區域C,當A第一次讀取C時經過缺頁從磁盤複製文件頁到內存中;但當B再讀C的相同頁面時,雖然也會產生缺頁異常,可是再也不須要從磁盤中複製文件過來,而可直接使用已經保存在內存中的文件數據。操作系統

mmap注意點

對於大文件而言,內存映射比普通IO流要快,小文件則未必; 不要常常調用MappedByteBuffer.force()方法,這個方法強制操做系統將內存中的內容寫入硬盤,因此若是你在每次寫內存映射文件後都調用force()方法,你就不能真正從內存映射文件中獲益,而是跟disk IO差很少。 讀寫內存映射文件是操做系統來負責的,所以,即便你的Java程序在寫入內存後就掛掉了,只要操做系統工做正常,數據就會寫入磁盤。 若是電源故障或者主機癱瘓,有可能內存映射文件尚未寫入磁盤,意味着可能會丟失一些關鍵數據。3d

參考

Android中的Binder也利用的mmap。Binder傳遞數據時,只須要複製一次,就能把數據傳遞到另外一個進程中。參考Binder機制介紹

Android中使用mmap

Android中使用mmap,能夠經過RandomAccessFile與MappedByteBuffer來配合。參考drone開發記錄 - log記錄工具

經過randomAccessFile.getChannel().map獲取到MappedByteBuffer。而後調用ByteBuffer的put方法添加數據。

相關文章
相關標籤/搜索