亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

深入了解Android?IO的底層原理

 更新時間:2022年06月22日 10:27:08   作者:??九心????  
這篇文章主要介紹了深入了解Android?IO的底層原理,IO有緩沖與非緩沖?IO、直接與非直接?IO、阻塞與非阻塞?IO、同步與異步?IO等分類,具體詳情感興趣的小伙伴可以參考下面文章內(nèi)容

前言

最近在看《Linux內(nèi)核設(shè)計與實現(xiàn)》的時候,就想著要不把知識串聯(lián)一下吧。聊什么呢?今天先來聊聊 Android IO 的調(diào)用鏈路。說起 IO,這可真是一個很復(fù)雜的過程,里面涉及了很多內(nèi)容,先是軟件,最后到硬件,用一張圖來表示一下吧:

IO結(jié)構(gòu).jpeg

本文打算簡單得和大伙討論一下 IO 的流程。

一、應(yīng)用層

作為應(yīng)用開發(fā)者,我們通常是 IO 發(fā)起點,比如用戶說這本小說很好看,我要下載到本地,或者,這張圖拍的不錯,分享給你看一下。

雖然這些都是常見的 IO 場景,但是你知道有哪些 IO 嗎?

1. IO的分類

通常去使用 IO 的時候,我們會有很多種選擇,常見的有:

  • 緩沖與非緩沖 IO
  • 直接與非直接 IO
  • 阻塞與非阻塞 IO
  • 同步與異步 IO

大家平時可能也就聽過緩沖 IO 和 阻塞 IO,這些可能是我們平時開發(fā)可能涉及到的。

1.1 緩沖和直接

前兩種分類都是使用緩存的。

緩沖是針對標(biāo)準(zhǔn)庫的。

Linux 標(biāo)準(zhǔn)庫定義了很多操作系統(tǒng)的基礎(chǔ)服務(wù),比如輸入/輸出、字符串處理等等。Android 操作系統(tǒng)的標(biāo)準(zhǔn)庫是 Bionic,它可是應(yīng)用層聯(lián)系內(nèi)核的橋梁,我們也可以通過 NDK 訪問 Bionic。

使用標(biāo)準(zhǔn)庫進行 IO 我們稱為緩沖 IO,我們讀文件的時候,經(jīng)常遇到,讀完一行才會讓輸出,在 Android 內(nèi)部也做了類似的處理。

直接是針對內(nèi)核的。

使用 Binder 跨進程傳遞數(shù)據(jù)的時候,需要將數(shù)據(jù)從用戶空間傳遞到內(nèi)核空間,非直接 IO 也這樣,內(nèi)核空間會多做一層頁緩存,如果做直接 IO,應(yīng)用程序會直接調(diào)用文件系統(tǒng)。

緩沖和非直接 IO 就像 IO 調(diào)度的一級和二級緩存,為什么要做這么多緩存呢?因為操作磁盤本身就是消耗資源的,不加緩存頻繁 IO 不僅會耗費資源也會耗時。

1.2 阻塞和異步

同步和異步我想大家都了解什么意思。

阻塞 IO指的是當(dāng)用戶執(zhí)行讀寫的時候,線程會一直阻塞,數(shù)據(jù)準(zhǔn)備和將數(shù)據(jù)拷貝到用戶進程都是阻塞的

Java 中的 NIO 是非阻塞 IO,當(dāng)用戶發(fā)起讀寫的時候,線程不會阻塞,之后,用戶可以通過輪詢或者接受通知的方式,獲取當(dāng)前 IO 調(diào)度的結(jié)果:

即使是非阻塞 IO,對于讀數(shù)據(jù)來說,也只有準(zhǔn)備數(shù)據(jù)的過程是異步,將數(shù)據(jù)從內(nèi)核拷貝到用戶進程這個過程還是同步的。所以非阻塞 IO 不能算是真正意義上的異步 IO

真正的異步 IO 應(yīng)該是這樣的:

準(zhǔn)備數(shù)據(jù)和將數(shù)據(jù)拷貝從內(nèi)核到用戶進程都應(yīng)該是異步的,當(dāng)收到通知的的時候,我們已經(jīng)可以在應(yīng)用進程使用數(shù)據(jù)了。

2. IO流程

作為應(yīng)用層開發(fā),大家做 IO 的場景并不多,最多也就是使用 BufferedInputStream 和 BufferedOutputStream 讀寫文件,至于 NIO ,那就更少見了。

我們了解一下阻塞 IO 的讀調(diào)用流程。

二、sysCall系統(tǒng)調(diào)用

應(yīng)用層調(diào)完了,下面會直接進入內(nèi)核嗎?

除去直接 IO,大部分都不會!用戶空間和內(nèi)核之間隔著一個系統(tǒng)調(diào)用(sysCall),它的作用如下:

  • 給用戶空間提供抽象的訪問硬件的接口:比如申請系統(tǒng)資源、操作設(shè)備讀寫等
  • 保證系統(tǒng)的安全和穩(wěn)定:內(nèi)核可以對用戶進程的訪問做出一些裁決,防止用戶進程做出一些危害系統(tǒng)的事情

畢竟內(nèi)核很復(fù)雜,抽象出通用的接口,可以防止用戶空間的進程僭越,獲取到它不該獲取的內(nèi)容。

為了能夠讓應(yīng)用進程聯(lián)系上內(nèi)核,它會通過一個軟中斷,通知內(nèi)核,我想調(diào)用內(nèi)核中 sysCall 中的讀接口。

對于讀 IO,系統(tǒng)調(diào)用中有一個 sys_read 方法與之對應(yīng),內(nèi)核收到通知執(zhí)行該方法的時候,就會執(zhí)行虛擬文件系統(tǒng)的 read 方法。

三、虛擬文件系統(tǒng)

文件系統(tǒng)實在是太多了,比如我手機用戶空間的文件系統(tǒng)是 f2fs,系統(tǒng)空間的文件系統(tǒng)是 ext4。對于應(yīng)用程序來說,它就想調(diào)用個讀方法,不想管你手機的底層文件系統(tǒng)是什么!

虛擬文件系統(tǒng)就是來干這活的,它可以屏蔽具體的文件系統(tǒng),定義了一組所有文件系統(tǒng)都支持的數(shù)據(jù)結(jié)構(gòu)和標(biāo)準(zhǔn)接口。這樣,應(yīng)用層的程序員只需了解 VFS 提供的統(tǒng)一接口就行。

虛擬文件系統(tǒng)常被稱為 VFS(Virtual File System),下稱 VFS。

1. VFS結(jié)構(gòu)

VFS 采用的是面向?qū)ο蟮脑O(shè)計思路,它常常有下列的對象(C語言中的結(jié)構(gòu)體)構(gòu)成:

這些對象構(gòu)成了基本的虛擬文件系統(tǒng)。

不過,光有這些對象可不行,VFS 還得知道如何操作它們,所以,每個對象中還存在對應(yīng)的操作對象:

  • super_operation 對象:內(nèi)核針對超級塊所能調(diào)用的方法
  • inode_operation 對象:內(nèi)核針對索引結(jié)點所能調(diào)用的方法
  • dentry_operation 對象:內(nèi)核針對目錄項所能操作的方法
  • file_operation 對象:內(nèi)核針對進程中打開的文件所能操作的方法

大伙最熟悉的應(yīng)該是文件,這是我們能夠在進程中實實在在能夠操作的,比如,在文件的 file_operation 中,就有我們熟悉的讀、寫、拷貝、打開、寫入磁盤等方法。

不知道大伙兒有沒注意到,我特意標(biāo)注了超級塊和索引節(jié)點存在于內(nèi)存和磁盤,而目錄項和文件只存在于內(nèi)存。

我的理解是對于磁盤,索引節(jié)點已經(jīng)足夠記錄文件信息,并不需要目錄項再來記錄層級關(guān)系;而對于內(nèi)存來說,為了節(jié)省內(nèi)存,只會把需要用到的文件和目錄項所用到的索引節(jié)點加入內(nèi)存,文件系統(tǒng)只有被掛載的時候超級塊才會被加入到內(nèi)存中。

目錄項、索引節(jié)點、文件和超級塊結(jié)構(gòu)圖:

上面的結(jié)構(gòu)圖還有幾點要注意一下:

  • 目錄項不等于目錄這個概念,對于 /home/pic/a.jpg 來說,根目錄 / 、home 目錄、pic 目錄 和 a.jpg 都屬于目錄項
  • 每個目錄項都會持有索引節(jié)點的指針
  • 索引節(jié)點包含內(nèi)核在操作文件需要的全部信息,比如存在磁盤的位置等
  • 進程中打開的文件持有目錄項

2. VFS中的緩存

結(jié)合本文中的第一張圖,我們會發(fā)現(xiàn),VFS 有目錄項緩存、索引節(jié)點緩存和頁緩存,目錄項和索引節(jié)點我們都知道什么意思,那頁緩存呢?

頁緩存是由 RAM 中的物理頁組成的,對應(yīng)著 ROM 上的物理地址。我們都知道,現(xiàn)在主流 Android 的 RAM 訪問速度高達是 8.5 GB/S,而 ROM 的訪問速度最高只有 6400 MB/S,所以訪問 RAM 的速度要遠(yuǎn)遠(yuǎn)快于 ROM,頁緩存的目的也在于此。

當(dāng)發(fā)起一個讀操作的時候,內(nèi)核會首先檢查需要的數(shù)據(jù)是否在頁緩存,如果在,直接從內(nèi)存中讀取,我們稱之為緩存命中;如果不在,那么內(nèi)核在讀取數(shù)據(jù)的時候,將讀到的數(shù)據(jù)放入頁緩存,需要注意的是,頁緩存可以存入全部文件內(nèi)容,也可以僅僅存幾頁。

3. IO流程

經(jīng)過系統(tǒng)調(diào)用,讀 IO 進入了 VFS。

就去找文件對象(VFS 中的),通過文件對象的 file_operation 對象,調(diào)用 read 方法,傳入讀取的數(shù)據(jù)量。不過 read 方法也是找到文件對象對應(yīng)的目錄項,目錄項又找到索引節(jié)點,畢竟,只有索引節(jié)點知道文件存在哪兒?

通過索引節(jié)點,內(nèi)核就能唯一確定一個文件,然后在頁緩存中尋找是否有自己需要的數(shù)據(jù),找到就直接返回。沒找到就去進行下一步的操作。

四、文件系統(tǒng)

VFS 定義了文件系統(tǒng)的統(tǒng)一接口,具體的實現(xiàn)了交給了文件系統(tǒng),超級塊里面的數(shù)據(jù)如何組織、目錄和索引結(jié)構(gòu)如何設(shè)計、怎么分配和清理數(shù)據(jù),這都是設(shè)計一個文件系統(tǒng)必須考慮的!

說白了,文件系統(tǒng)就是用來管理磁盤里的持久化的數(shù)據(jù)的,對于 Android 來說,最常見的就是 ext4 和 f2fs。

1. 文件系統(tǒng)結(jié)構(gòu)

因為文件系統(tǒng)是 VFS 的具體實現(xiàn),所以同樣有目錄項、索引節(jié)點和超級塊,上面的圖片用來描述文件系統(tǒng)也同樣適合。

拿早起 ext2 的系統(tǒng)結(jié)構(gòu)來講:

每一個 ext2 都由大量的塊組組成,每個塊組的結(jié)構(gòu)就跟上面的目錄項和索引節(jié)點中的圖一樣??梢钥吹?,在 inode 列表,存在著很多數(shù)據(jù)塊,塊是內(nèi)存中最小的尋址單元,見于磁盤中的章節(jié),一般可以設(shè)置帶大小為 2kb - 64kb 之間。

2. 文件系統(tǒng)的不同點

雖然大部分的文件系統(tǒng)也都有超級塊、索引節(jié)點和數(shù)據(jù)塊,但是各個文件系統(tǒng)的實現(xiàn)卻大不相同,這就導(dǎo)致了他們的側(cè)重點也不一樣。

拿 ext4 和 f2fs 來講:

  • ext4連續(xù)讀取大文件更強,占用的空間更小
  • f2fs隨機 IO 更快

說白了,也就是它們對于空閑空間分配和已有的數(shù)據(jù)管理方式不一致,不同的數(shù)據(jù)結(jié)構(gòu)和算法導(dǎo)致了不同的結(jié)果。

3. IO流程

這里的 IO 流程其實跟 VFS 差不多,畢竟文件系統(tǒng)是 VFS 的具體實現(xiàn)。

五、塊IO層

Linux 下面有兩大基本設(shè)備類型:

  • 塊設(shè)備:能夠隨機訪問固定大小數(shù)據(jù)片的硬件設(shè)備,硬盤和閃存(下面介紹)就是常見的塊設(shè)備
  • 字符設(shè)備:字符設(shè)備只能按照字符流的方式被有序訪問,比如鍵盤和串口

這兩個設(shè)備的區(qū)別就是是否能夠隨機訪問。拿屬于字符設(shè)備的鍵盤來說,當(dāng)我們輸入 Hello World 的時候,系統(tǒng)肯定不可以先得到得到 eholl wrodl,這樣的話,輸出就亂套了。而對于閃存來說,常常是看完這個這些數(shù)據(jù)庫組成的圖片,又要讀間隔很遠(yuǎn)的數(shù)組塊的小說內(nèi)容,所以讀取的塊在磁盤上肯定不是連續(xù)的。

因為內(nèi)核管理塊設(shè)備實在太復(fù)雜了,所以就出現(xiàn)了管理塊設(shè)備的子系統(tǒng),就是上面說的文件系統(tǒng)。

1. 塊設(shè)備結(jié)構(gòu)

塊設(shè)備中常用的數(shù)據(jù)管理單位:

  • 扇區(qū):設(shè)備的最小尋址單元
  • 塊:文件系統(tǒng)的最小尋址單元,數(shù)倍大于扇區(qū)
  • 片段:由數(shù)百至數(shù)千的塊組成

因為 Linux 中常常用的硬盤,這里我有點疑問,這里的管理單位是否和下面閃存管理單位一致?

2. IO過程

如果當(dāng)前有 IO 操作,內(nèi)核會建立一個 bio 結(jié)構(gòu)體的基本容器,它是由多個片段組成,每一個片段都是一小塊連續(xù)的內(nèi)存緩沖區(qū)。

之后,內(nèi)核會將這些 IO 請求保存在一個 request_queue 的請求隊列中。

如果按照 IO 請求產(chǎn)生的順序發(fā)向塊設(shè)備,性能肯定難以接受,所以內(nèi)核會按照磁盤地址對進入隊列之前提交的 IO 請求做合并與排序的預(yù)操作。

六、磁盤

移動設(shè)備中常用的持久化存儲是 Nand 閃存,UFS 又是 Nand 閃存中的佼佼者,其特點是速度更快、體積小和更省電。

當(dāng)今 Android 旗艦機基本上標(biāo)配 UFS 3.1,它們只是一塊兒很小的芯片:

閃存是一種非易失性存儲器,即使掉電了,數(shù)據(jù)也不會丟。閃存的存儲單元從小到大有:

  • Cell(單元):是閃存存儲的最小單位,根據(jù)存儲的數(shù)量可以分為SLC(1bit/Cell)、MLC(2bit/Cell)、TLC(3bit/Cell)和QLC(4bit/Cell)
  • Page(頁):由大量的 Cell 構(gòu)成,每個 Page 的大小通常是 16 kb,它是閃存能夠讀取的和寫入的最小單位
  • Block(塊):每個塊由數(shù)百至數(shù)千的 Page 組成
  • Plane(面):Plane 由數(shù)百至數(shù)千的 Black 組成
  • Die(邏輯單元):每個 Die 由一個至多個 Plane,是閃存中可以執(zhí)行命令或者回報狀態(tài)的最小單元

對于每個 Cell 來說,是由一種類 NMOS 的雙層浮柵 MOS 管組成,大概是這樣:

對于 SLC(存儲1bit)來說:

  • 如果需要1,在 P 極施加一個電壓,將電子吸出儲存單元
  • 如果需要0,需要在頂層的控制極施加一個電壓,讓電子吸回存儲單元

這就構(gòu)成了數(shù)據(jù)存儲的最小單位,0和1!

總結(jié)

整個流程簡要的用一張圖來表示:

因為我對內(nèi)核也不是特別熟,文中難免有不對的地方,歡迎在評論區(qū)指正,如果覺得本文不錯,「點贊」是最好的肯定!

到此這篇關(guān)于深入了解Android IO的底層原理的文章就介紹到這了,更多相關(guān) Android IO原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Android自定義可標(biāo)記日歷效果

    Android自定義可標(biāo)記日歷效果

    這篇文章主要為大家詳細(xì)介紹了Android自定義可標(biāo)記日歷效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android實現(xiàn)五子棋游戲(局域網(wǎng)版)

    Android實現(xiàn)五子棋游戲(局域網(wǎng)版)

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)局域網(wǎng)版的五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Android入門之TextClock的使用教程

    Android入門之TextClock的使用教程

    TextClock是在Android 4.2(API 17)后推出的用來替代DigitalClock的一個控件。本文將為大家詳細(xì)說說TextClock的使用,感興趣的小伙伴可以了解一下
    2022-11-11
  • Android自定義Camera實現(xiàn)拍照小功能

    Android自定義Camera實現(xiàn)拍照小功能

    這篇文章主要為大家詳細(xì)介紹了Android自定義Camera實現(xiàn)拍照小功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-05-05
  • Android開發(fā)之廣播機制淺析

    Android開發(fā)之廣播機制淺析

    這篇文章主要介紹了Android開發(fā)之廣播機制淺析,主要包括了發(fā)布、接收及配置廣播的實例,需要的朋友可以參考下
    2014-08-08
  • Android ActivityManagerService啟動流程詳解

    Android ActivityManagerService啟動流程詳解

    這篇文章主要介紹了Android ActivityManagerService啟動流程,AMS,即ActivityManagerService,是安卓java framework的一個服務(wù),運行在system_server進程。此服務(wù)十分重要,因為它管理著安卓的四大組件,是安卓APP開發(fā)者最常接觸到的一個服務(wù)
    2023-02-02
  • Android編程實現(xiàn)兩點觸控功能示例

    Android編程實現(xiàn)兩點觸控功能示例

    這篇文章主要介紹了Android編程實現(xiàn)兩點觸控功能的方法,涉及Android事件響應(yīng)與處理相關(guān)操作技巧,需要的朋友可以參考下
    2017-08-08
  • Android屬性動畫實現(xiàn)圖片從左到右逐漸消失

    Android屬性動畫實現(xiàn)圖片從左到右逐漸消失

    這篇文章主要介紹了Android屬性動畫實現(xiàn)圖片從左到右逐漸消失,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-11-11
  • 協(xié)程作用域概念迭代RxTask?實現(xiàn)自主控制

    協(xié)程作用域概念迭代RxTask?實現(xiàn)自主控制

    這篇文章主要為大家介紹了協(xié)程作用域概念迭代RxTask實現(xiàn)自主控制詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • flutter Toast實現(xiàn)消息提示框

    flutter Toast實現(xiàn)消息提示框

    這篇文章主要為大家詳細(xì)介紹了flutter Toast實現(xiàn)消息提示框,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-07-07

最新評論