Android I/O 那些事兒

I/O 操作是編程離不開的話題,它不僅是讀寫那么簡單绞呈,還涉及底層的文件系統(tǒng)和存儲設(shè)備兔毙。I/O 的快慢影響程序的執(zhí)行效率柠辞,這篇文章主要介紹 Android 平臺 I/O 的方式和使用場景尘颓。

1. Linux I/O 的基本組成

眾所周知走触,Android 基于 Linux 系統(tǒng),先介紹一些 Linux 上 I/O 的知識疤苹。

I/O 操作由應(yīng)用程序互广、文件系統(tǒng)和磁盤共同完成,應(yīng)用程序?qū)?I/O 命令發(fā)送給文件系統(tǒng)卧土,文件系統(tǒng)在合適的時間把 I/O 指令發(fā)送給磁盤凸椿。I/O 的流程如下圖:

I/O操作

CPU 和內(nèi)存的速度比磁盤快得多,I/O 操作的瓶頸在于磁盤的性能隘庄。為了降低磁盤對應(yīng)用程序的影響囤官,文件系統(tǒng)要進(jìn)行各種各樣的優(yōu)化。

文件系統(tǒng)

簡單來說颤霎,文件系統(tǒng)就是存儲和組織數(shù)據(jù)的方式媳谁。應(yīng)用程序調(diào)用 read() 方法,系統(tǒng)會通過中斷從用戶空間進(jìn)入內(nèi)核空間友酱,然后經(jīng)過虛擬文件系統(tǒng)晴音、具體文件系統(tǒng)、頁緩存缔杉。

Linux-I/O架構(gòu)
  • 虛擬文件系統(tǒng)(VFS)锤躁。主要用于屏蔽具體的文件系統(tǒng),為應(yīng)用程序的操作提供一個統(tǒng)一的接口或详。
  • 文件系統(tǒng)(File System)系羞。ext4、F2FS 都是具體文件系統(tǒng)實現(xiàn)霸琴。每個文件系統(tǒng)都有適合自己的場景椒振。
  • 頁緩存(Page Cache)。文件系統(tǒng)對數(shù)據(jù)的緩存沈贝,讀文件時先檢查頁緩存杠人,如果命中就不去讀磁盤。

磁盤

磁盤指的是系統(tǒng)的存儲設(shè)備宋下,常見的有機(jī)械硬盤嗡善、固態(tài)硬盤等。如果發(fā)現(xiàn)應(yīng)用程序要讀的數(shù)據(jù)沒有在頁緩存中学歧,這時候就需要真正向磁盤發(fā)起 I/O 請求罩引。磁盤 I/O 的過程要先經(jīng)過內(nèi)核的通用塊層、I/O 調(diào)度層枝笨、設(shè)備驅(qū)動層袁铐,最后才會交給具體的硬件設(shè)備處理揭蜒。

磁盤架構(gòu)
  • 通用塊層。接收上層發(fā)出的磁盤請求剔桨,并最終發(fā)出 I/O 請求屉更。它與 VPS 的作用類似。
  • I/O 調(diào)度層洒缀。根據(jù)設(shè)置的調(diào)度算法對請求合并和排序瑰谜。不能接收到磁盤請求就立刻交給驅(qū)動層處理。
  • 塊設(shè)備驅(qū)動層树绩。根據(jù)具體的物理設(shè)備萨脑,選擇對應(yīng)的驅(qū)動程序,通過操控硬件設(shè)備完成最終的 I/O 請求饺饭。

2. Android 上的 I/O

Android 現(xiàn)在普遍使用的是 Linux 常用的 ext4 文件系統(tǒng)渤早。F2FS(Flash-Friendly File System)是三星為閃存研發(fā)的文件系統(tǒng),它針對閃存進(jìn)行了大量優(yōu)化瘫俊,F(xiàn)2FS 文件系統(tǒng)在小文件的隨機(jī)讀寫方面比 ext4 更快鹊杖。隨著 Google、華為的投入和使用军援,F(xiàn)2FS 應(yīng)該會成為 Android 主流的文件系統(tǒng)仅淑。

Android 手機(jī)使用閃存作為存儲設(shè)備称勋,也就是我們常說的 ROM胸哥。前幾年閃存通常使用 eMMC 標(biāo)準(zhǔn),近年來采用性能更好的 UFS 2.0/2.1 標(biāo)準(zhǔn)赡鲜。手機(jī)存儲也朝著體積更小空厌、功耗更低、速度更快银酬、容量更大的方向發(fā)展嘲更,閃存的隨機(jī)讀寫速度甚至比 SSD 還快。

手機(jī)變卡

Android 手機(jī)用久了會變卡揩瞪,除了系統(tǒng)升級赋朦、設(shè)備折舊等因素,還和 I/O 有密切關(guān)系李破。I/O 操作變慢的原因有下面幾條:

  • 內(nèi)存不足宠哄。系統(tǒng)回收 Page Cache 和 Buffer Cache 的內(nèi)存,大部分的寫操作會直接落盤嗤攻,導(dǎo)致性能低下毛嫉。
  • 寫入放大。閃存重復(fù)寫入需要先進(jìn)行擦除妇菱,一次寫入會引起整個塊數(shù)據(jù)的遷移承粤,導(dǎo)致寫入時間非常久暴区。
  • 設(shè)備性能差。在高負(fù)載的情況下容易出現(xiàn)瓶頸辛臊。

文件損壞

文件損壞是令人頭疼的問題仙粱,大多是由不正確的操作導(dǎo)致的。文件損壞的原因可以從應(yīng)用程序彻舰、文件系統(tǒng)和磁盤三個角度來分析:

  • 應(yīng)用程序缰盏。大部分的 I/O 方法都不是原子操作,文件的跨進(jìn)程或者多線程寫入淹遵、使用一個已經(jīng)關(guān)閉的文件描述符 fd 來操作文件口猜,都有可能導(dǎo)致數(shù)據(jù)被覆蓋或者刪除。
  • 文件系統(tǒng)透揣。雖說內(nèi)核崩潰或者系統(tǒng)突然斷電都有可能導(dǎo)致文件系統(tǒng)損壞济炎,不過文件系統(tǒng)也做了很多的保護(hù)措施。例如 system 分區(qū)保證只讀不可寫辐真,增加異常檢查和恢復(fù)機(jī)制须尚。
  • 磁盤。手機(jī)上使用的閃存是電子式的存儲設(shè)備侍咱,所以在資料傳輸過程可能會發(fā)生電子遺失等現(xiàn)象導(dǎo)致數(shù)據(jù)錯誤耐床。

3. I/O 的三種方式

I/O 有三種方式:標(biāo)準(zhǔn) I/O、mmap 和 Direct I/O楔脯。

I/O的方式

標(biāo)準(zhǔn) I/O

應(yīng)用程序平時用到 read/write 操作都屬于標(biāo)準(zhǔn) I/O撩轰,也就是緩存 I/O(Buffered I/O)。它的關(guān)鍵特性有:

  • 對于讀操作昧廷,當(dāng)應(yīng)用程序讀取某塊數(shù)據(jù)時堪嫂,如果這塊數(shù)據(jù)已經(jīng)在頁緩存中,那么就不需要經(jīng)過物理讀盤操作木柬。
  • 對于寫操作皆串,應(yīng)用程序會先將數(shù)據(jù)寫到頁緩存中去,不需要等全部數(shù)據(jù)被寫回磁盤眉枕,系統(tǒng)會定期將頁緩存中的數(shù)據(jù)刷到磁盤上恶复。

緩存 I/O 可以很大程度減少真正讀寫磁盤的次數(shù),從而提升性能速挑。但是延遲寫機(jī)制可能會導(dǎo)致數(shù)據(jù)丟失谤牡。在實際應(yīng)用中,如果某些數(shù)據(jù)非常重要梗摇,我們應(yīng)該采用同步寫機(jī)制拓哟。

讀操作時,數(shù)據(jù)會先從磁盤拷貝到 Page Cache 中伶授,然后再從 Page Cache 拷貝到應(yīng)用程序的用戶空間断序,這樣就會多一次內(nèi)存拷貝流纹。內(nèi)存相對磁盤是高速設(shè)備,即使多拷貝一次违诗,也比真正讀一次硬盤要快漱凝。

mmap

mmap 把文件映射到進(jìn)程的地址空間,提高了 I/O 的性能诸迟。

mmap 的優(yōu)點有:

  • 減少系統(tǒng)調(diào)用茸炒。只需要一次 mmap() 系統(tǒng)調(diào)用,后續(xù)所有的調(diào)用像操作內(nèi)存一樣阵苇。
  • 減少數(shù)據(jù)拷貝壁公。mmap 只需要從磁盤拷貝一次,由于做過內(nèi)存映射绅项,不需要再拷貝回用戶空間紊册。
  • 可靠性高。mmap 把數(shù)據(jù)寫入頁緩存后快耿,跟緩存 I/O 的延遲寫機(jī)制一樣囊陡。

存在的缺點:

  • 虛擬內(nèi)存增大。Apk掀亥、Dex撞反、so 都是通過 mmap 讀取。mmap 會導(dǎo)致虛擬內(nèi)存增大搪花,mmap 大文件容易出現(xiàn) OOM遏片。
  • 磁盤延遲。mmap 通過缺頁中斷向磁盤發(fā)起真正的磁盤 I/O鳍侣,不能通過 mmap 消除磁盤 I/O 的延遲丁稀。

在 Android 中可以將文件通過 MemoryFile 或者 MappedByteBuffer 映射到內(nèi)存,然后進(jìn)行讀寫倚聚,使用這種方式對于小文件和頻繁讀寫操作的文件還是有一定優(yōu)勢的。

mmap 比較適合對同一塊區(qū)域頻繁讀寫的情況凿可,推薦使用 I/O 線程來操作惑折。用戶日志、數(shù)據(jù)上報都滿足這種場景枯跑,另外需要跨進(jìn)程同步的時候惨驶,mmap 也是一個不錯的選擇。Android 跨進(jìn)程通信有自己獨有的 Binder 機(jī)制敛助,它內(nèi)部也是使用 mmap 實現(xiàn)粗卜。

Direct I/O

一些數(shù)據(jù)庫自己實現(xiàn)了數(shù)據(jù)和索引的緩存管理,對頁緩存的依賴沒那么強(qiáng)烈纳击。它們想繞開頁緩存機(jī)制续扔,減少一次數(shù)據(jù)拷貝攻臀,它的數(shù)據(jù)也不會污染頁緩存。

直接 I/O 訪問文件方式減少了一次數(shù)據(jù)拷貝和一些系統(tǒng)調(diào)用的耗時纱昧,很大程度降低了 CPU 的使用率以及內(nèi)存的占用刨啸。負(fù)面影響就是讀寫操作都是同步執(zhí)行,導(dǎo)致應(yīng)用程序等待识脆。

4. 同步與異步 I/O

多線程阻塞式在 I/O 操作上的并沒有優(yōu)勢设联,I/O 操作的主要瓶頸在于磁盤帶寬。所以 I/O 操作不能開大量的線程灼捂。

NIO 是非阻塞 I/O离例,將 I/O 以事件的方式通知,可以減少線程切換的開銷悉稠。NIO 的最大作用不是減少讀取文件的耗時粘招,而是最大化提升應(yīng)用整體的 CPU 利用率。

另外偎球,非常推薦 Square 的 Okio洒扎,它支持同步和異步 I/O,也做了比較多的優(yōu)化衰絮。

I/O 優(yōu)化對提升應(yīng)用的體驗非常有用袍冷,希望上面所講的內(nèi)容對你有幫助。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末猫牡,一起剝皮案震驚了整個濱河市胡诗,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淌友,老刑警劉巖煌恢,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異震庭,居然都是意外死亡瑰抵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進(jìn)店門器联,熙熙樓的掌柜王于貴愁眉苦臉地迎上來二汛,“玉大人,你說我怎么就攤上這事拨拓‰燃眨” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵渣磷,是天一觀的道長婿着。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么竟宋? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任提完,我火速辦了婚禮,結(jié)果婚禮上袜硫,老公的妹妹穿的比我還像新娘氯葬。我一直安慰自己,他們只是感情好婉陷,可當(dāng)我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布帚称。 她就那樣靜靜地躺著,像睡著了一般秽澳。 火紅的嫁衣襯著肌膚如雪闯睹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天担神,我揣著相機(jī)與錄音楼吃,去河邊找鬼。 笑死妄讯,一個胖子當(dāng)著我的面吹牛孩锡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播亥贸,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼躬窜,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了炕置?” 一聲冷哼從身側(cè)響起荣挨,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎朴摊,沒想到半個月后默垄,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡甚纲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年口锭,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贩疙。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡讹弯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出这溅,到底是詐尸還是另有隱情,我是刑警寧澤棒仍,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布悲靴,位于F島的核電站,受9級特大地震影響莫其,放射性物質(zhì)發(fā)生泄漏癞尚。R本人自食惡果不足惜耸三,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望浇揩。 院中可真熱鬧仪壮,春花似錦、人聲如沸胳徽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽养盗。三九已至缚陷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間往核,已是汗流浹背箫爷。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留聂儒,地道東北人虎锚。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像衩婚,于是被迫代替她去往敵國和親窜护。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容

  • 今天看到一位朋友寫的mysql筆記總結(jié)谅猾,覺得寫的很詳細(xì)很用心柄慰,這里轉(zhuǎn)載一下,供大家參考下税娜,也希望大家能關(guān)注他原文地...
    信仰與初衷閱讀 4,725評論 0 30
  • feisky云計算坐搔、虛擬化與Linux技術(shù)筆記posts - 1014, comments - 298, trac...
    不排版閱讀 3,815評論 0 5
  • ORA-00001: 違反唯一約束條件 (.) 錯誤說明:當(dāng)在唯一索引所對應(yīng)的列上鍵入重復(fù)值時,會觸發(fā)此異常敬矩。 O...
    我想起個好名字閱讀 5,189評論 0 9
  • 從這一章開始概行,我們探討的話題就會與前面的話題稍有不同——我們將開始探討操作系統(tǒng)對于設(shè)備的管理以及它為用戶程序提供服...
    夏威夷的芒果閱讀 1,379評論 0 0
  • 前言:在之前的面試中禽炬,每每問到關(guān)于Java I/O 方面的東西都感覺自己吃了大虧..所以這里搶救一下..來深入的了...
    我沒有三顆心臟閱讀 2,484評論 0 21