在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

讀取文件1個字節是否會導致磁盤IO?

開關電源芯片 ? 來源:開發內功修煉 ? 作者:zhangyanfei01 ? 2021-07-09 09:42 ? 次閱讀

在日常開發中一些看似司空見慣的問題上,我覺得可能大多數人其實并沒有真正理解,或者理解的不夠透徹。不信我們來看以下一段簡單的讀取文件的代碼:

上圖中的代碼僅僅只是對某個文件讀取了一個字節,基于這個代碼片段我們來思考:

1、讀取文件 1 個字節是否會導致磁盤 IO ?

2、如果發生了磁盤 IO,那發生的是多大的 IO 呢?

大家平時用的各種語言 C++、PHP、Java、Go 啥的封裝層次都比較高,把很多細節都給屏蔽的比較徹底。如果想把上面的問題搞清楚,需要剖開 Linux 的內部來看 Linux 的 IO 棧。

一、大話 Linux IO 棧

廢話不多說,我畫了一個 Linux IO 棧的簡化版本。

通過 IO 棧可以看到,我們在應用層簡單的一次 read 而已,內核就需要 IO 引擎、VFS、PageCache、通用塊管理層、IO 調度層等許多個組件來進行復雜配合才能完成。

那這些組件都是干啥的呢?我們挨個簡單過一遍。不想看這個的同學可以直接跳到第二節的讀文件讀過程。

1.1 IO 引擎

開發同學想要讀寫文件的話,在 lib 庫層有很多套函數可以選擇,比如 read & write,pread & pwrite。這事實上就是在選擇 Linux 提供的 IO 引擎。

我們開篇中代碼片用的 read 函數就屬于 sync 引擎。IO 引擎仍然處于上層,它需要內核層的提供的系統調用、VFS、通用塊層等更底層組件的支持才能實現。

接著讓我們繼續深入到內核,來介紹各個內核組件。

1.2 系統調用

當進入到系統調用以后,也就進入到了內核層。

系統調用將內核中其它組件的功能進行封裝,然后通過接口的形式暴露給用戶進程來訪問。

對于我們的讀取文件的需求,系統調用需要依賴 VFS 內核組件。

1.3 VFS 虛擬文件系統

VFS 的思想就是在 Linux 上抽象一個通用的文件系統模型,對我們開發人員或者是用戶提供一組通用的接口,讓我們不用 care 具體文件系統的實現。VFS 提供的核心數據結構有四個,它們定義在內核源代碼的 include/linux/fs.h 和 include/linux/dcache.h 中。

superblock:Linux 用來標注具體已安裝的文件系統的有關信息

inode:Linux 中的每一個文件/目錄都有一個 inode,記錄其權限、修改時間等信息。

desty:目錄項,是路徑中的一部分,所有的目錄項對象串起來就是一棵 Linux 下的目錄樹。

file:文件對象,用來和打開它的進程進行交互。

圍繞這這四個核心數據結構,VFS 也都定義了一系列的操作方法。比如,inode 的操作方法定義 inode_operations,在它的里面定義了我們非常熟悉的 mkdir 和 rename 等。對于 file 對象,定義了對應的操作方法 file_operations ,如下:

// include/linux/fs.hstruct file {

。。。。。。

const struct file_operations *f_op

}

struct file_operations {

。。。。。。

ssize_t (*read) (struct file *, char __user *, size_t, loff_t *);

ssize_t (*write) (struct file *, const char __user *, size_t, loff_t *);

。。。。。。

int (*mmap) (struct file *, struct vm_area_struct *);

int (*open) (struct inode *, struct file *);

int (*flush) (struct file *, fl_owner_t id);

}

注意 VFS 是抽象的,所以它的 file_operations 里定義的 read、write 都只是函數指針, 實際中需要具體的文件系統來實現,例如 ext4 等等。

1.4 Page Cache

Page Cache。它的中文譯名叫頁高速緩存。它是 Linux 內核使用的主要磁盤高速緩存,是一個純內存的工作組件。Linux 內核使用搜索樹來高效管理大量的頁面。

有了它,Linux 就可以把一些磁盤上的文件數據保留在內存中,然后來給訪問相對比較慢的磁盤來進行訪問加速。

當用戶要訪問的文件的時候,如果要訪問的文件 block 正好存在于 Page Cache 內,那么 Page Cache 組件直接把數據從內核態拷貝到用戶進程的內存中就可以了。如果不存在,那么會申請一個新頁,發出缺頁中斷,然后用磁盤讀取到的 block 內容來填充它 ,下次直接使用。

看到這里,開篇的問題可能你就明白一半了,如果你要訪問的文件近期訪問過,那么 Linux 大概率就是從 Page cache 內存中的拷貝給你就完事,并不會有實際的磁盤 IO 發生。

不過有一種情況下,Pagecache 不會生效, 那就是你設置了 DIRECT_IO 標志。

1.5 文件系統

Linux 下支持的文件系統有很多,常用的有 ext2/3/4、XFS、ZFS 等。

要用哪種文件系統是在格式化的時候指定的。因為每一個分區都可以單獨進行格式化,所以一臺 Linux 機器下可以同時使用多個不同的文件系統。

文件系統里提供對 VFS 的具體實現。除了數據結構,每個文件系統還會定義自己的實際操作函數。例如在 ext4 中定義的 ext4_file_operations。在其中包含的VFS中定義的 read 函數的具體實現:do_sync_read 和 do_sync_write。

const struct file_operations ext4_file_operations = {

.llseek = ext4_llseek,

.read = do_sync_read,

.write = do_sync_write,

.aio_read = generic_file_aio_read,

.aio_write = ext4_file_write,

。。。。。。

}

和 VFS 不同的是,這里的函數就是實實在在的實現了。

1.6 通用塊層

文件系統還要依賴更下層的通用塊層。

對上層的文件系統,通用塊層提供一個統一的接口讓供文件系統實現者使用,而不用關心不同設備驅動程序的差異,這樣實現出來的文件系統就能用于任何的塊設備。通過對設備進行抽象后,不管是磁盤還是機械硬盤,對于文件系統都可以使用相同的接口對邏輯數據塊進行讀寫操作。

對下層。I/O 請求添加到設備的 I/O 請求隊列。它定義了一個叫 bio 的數據結構來表示一次 IO 操作請求(include/linux/bio.h)

1.7 IO 調度層

當通用塊層把 IO 請求實際發出以后,并不一定會立即被執行。因為調度層會從全局出發,盡量讓整體磁盤 IO 性能最大化。

對于機械硬盤來說,調度層會盡量讓磁頭類似電梯那樣工作,先往一個方向走,到頭再回來,這樣整體效率會比較高一些。具體的算法有 deadline 和 cfg ,算法細節就不展開了,感興趣同學可以自行搜索。

對于固態硬盤來說,隨機 IO 的問題已經被很大程度地解決了,所以可以直接使用最簡單的 noop 調度器。

在你的機器上,通過dmesg | grep -i scheduler來查看你的 Linux 支持的調度算法。

通用塊層和 IO 調度層一起為上層文件系統屏蔽了底層各種不同的硬盤、U盤的設備差異。

二、讀文件過程

我們已經把 Linux IO 棧里的各個內核組件都簡單介紹一遍了。現在我們再從頭整體過一下讀取文件的過程

三、回顧開篇問題

回到開篇的第一個問題:讀取文件 1 個字節是否會導致磁盤 IO ?

從上述流程中可以看到,如果 Page Cache 命中的話,根本就沒有磁盤 IO 產生。

所以,大家不要覺得代碼里出現幾個讀寫文件的邏輯就覺得性能會慢的不行。操作系統已經替你優化了很多很多,內存級別的訪問延遲大約是 ns 級別的,比機械磁盤 IO 快了好幾個數量級。如果你的內存足夠大,或者你的文件被訪問的足夠頻繁,其實這時候的 read 操作極少有真正的磁盤 IO 發生。

假如 Page Cache 沒有命中,那么一定會有傳動到機械軸上進行磁盤 IO 嗎?

其實也不一定,為什么,因為現在的磁盤本身就會帶一塊緩存。另外現在的服務器都會組建磁盤陣列,在磁盤陣列里的核心硬件Raid卡里也會集成RAM作為緩存。只有所有的緩存都不命中的時候,機械軸帶著磁頭才會真正工作。

再看開篇的第二個問題:如果發生了磁盤 IO,那發生的是多大的 IO 呢?

如果所有的 Cache 都沒有兜住 IO 讀請求,那么我們來看看實際 Linux 會讀取多大。真的按我們的需求來,只去讀一個字節嗎?

整個 IO 過程中涉及到了好幾個內核組件。而每個組件之間都是采用不同長度的塊來管理磁盤數據的。

Page Cache 是以頁為單位的,Linux 頁大小一般是 4KB

文件系統是以塊(block)為單位來管理的。使用 dumpe2fs 可以查看,一般一個塊默認是 4KB

通用塊層是以段為單位來處理磁盤 IO 請求的,一個段為一個頁或者是頁的一部分

IO 調度程序通過 DMA 方式傳輸 N 個扇區到內存,扇區一般為 512 字節

硬盤也是采用“扇區”的管理和傳輸數據的

可以看到,雖然我們從用戶角度確實是只讀了 1 個字節(開篇的代碼中我們只給這次磁盤IO留了一個字節的緩存區)。但是在整個內核工作流中,最小的工作單位是磁盤的扇區,為512字節,比1個字節要大的多。

另外 block、page cache 等高層組件工作單位更大。其中 Page Cache 的大小是一個內存頁 4KB。所以一般一次磁盤讀取是多個扇區(512字節)一起進行的。假設通用塊層 IO 的段就是一個內存頁的話,一次磁盤 IO 就是 4 KB(8 個 512 字節的扇區)一起進行讀取。

另外我們沒有講到的是還有一套復雜的預讀取的策略。所以,在實踐中,可能比 8 更多的扇區來一起被傳輸到內存中。

最后,啰嗦幾句

操作系統的本意是做到讓你簡單可依賴, 讓你盡量把它當成一個黑盒。你想要一個字節,它就給你一個字節,但是自己默默干了許許多多的活兒。

我們雖然國內絕大多數開發都不是搞底層的,但如果你十分關注你的應用程序的性能,你應該明白操作系統的什么時候悄悄提高了你的性能,是怎么來提高的。以便在將來某一個時候你的線上服務器扛不住快要掛掉的時候,你能迅速找出問題所在。

想繼續深入學習的同學可以參考《深入理解 Linux 內核》之第十四章。

編輯:jq

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • Linux
    +關注

    關注

    87

    文章

    11342

    瀏覽量

    210222

原文標題:read 文件一個字節實際會發生多大的磁盤IO?

文章出處:【微信號:gh_3980db2283cd,微信公眾號:開關電源芯片】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    請問一下ADS1293讀取某一通道的高低2個字節的PACE數據,如何判斷這是有效的PACE信號?

    請問一下ADS1293讀取某一通道的高低2個字節的PACE數據,但是如何判斷這是有效的PACE信號? 在處理的時候,根據是否是有效的PACE數據,才可以在ECG中設置起搏標志。
    發表于 01-06 07:43

    用ads1158在讀取數據的時候,后面兩個字節的數據讀不到,為什么?

    我現在用的ads1158在讀取數據的時候,通道號是可以正常讀取的,但是后面兩個字節的數據讀不到,不管輸入信號怎么變化,讀到的兩個字節數據始終是一
    發表于 12-24 06:16

    什么是raid磁盤冗余陣列

    讀寫、如實現數據備份。 ? raid技術的作用 ? - 提高IO能力,磁盤并行讀寫 - 提高耐用性,磁盤冗余算法來實現- 具備冗余功能,節約成本 ? raid級別的作用、以及區別 ? - raid0 最小
    的頭像 發表于 12-16 16:41 ?287次閱讀
    什么是raid<b class='flag-5'>磁盤</b>冗余陣列

    華納云監視Linux磁盤IO性能命令:iotop,iostat,vmstat,atop,dstat,ioping

    以下介紹6監視 Linux 磁盤IO性能的命令(工具),它們分別是iotop、iostat、vmstat、atop、dstat、ioping,以下將附上簡單的使用方法。 前言 磁盤
    的頭像 發表于 10-24 14:43 ?253次閱讀

    嵌入式學習-飛凌嵌入式ElfBoard ELF 1板卡-通用文件IO模型之read

    至少應有count個字節; 有多種情況可能導致實際讀到的字節數小于要求讀的字節數: 一、普通文件:讀到要求的
    發表于 10-15 08:54

    飛凌嵌入式ElfBoard ELF 1板卡-通用文件IO模型之read

    count個字節;有多種情況可能導致實際讀到的字節數小于要求讀的字節數:一、普通文件:讀到要求的字節
    發表于 10-14 09:24

    Linux磁盤IO詳細解析

      在講解磁盤IO前,先簡單說下什么是磁盤磁盤是可以持久化存儲的設備,根據存儲介質的不同,常見磁盤可以分為兩類:機械
    的頭像 發表于 08-05 15:49 ?692次閱讀
    Linux<b class='flag-5'>磁盤</b><b class='flag-5'>IO</b>詳細解析

    ESP8266是否在所有5插槽的TX和RX中都只使用2048個字節

    ? wiz w5100 芯片內部有 16k 緩沖區,為 tx 和 rx 提供單獨的 2k for 4 插槽。 ESP8266 是否在所有 5 插槽的 TX 和 RX 中都只使用 2048
    發表于 07-12 13:17

    使用Vela IF820 DVK和EZ-Serial,傳輸幾千個字節時,接收端丟失數據的原因?

    我正在使用 Vela IF820 DVK(帶 MHF4 連接器)和 EZ-Serial,使用 BT Classic SPP 配置文件進行串行電纜更換應用。 傳輸幾百個字節時運行正常,但傳輸幾千個字節
    發表于 05-24 08:18

    EVA數據恢復—EVA存儲中磁盤掉線導致LUN丟失的數據恢復案例

    EVA存儲數據恢復環境: EVA控制器+三擴展柜+數十塊FC硬盤。 EVA存儲故障&檢測: 磁盤掉線導致存儲中的部分LUN丟失,部分LUN損壞不可用。 由于是磁盤掉線
    的頭像 發表于 04-19 13:28 ?429次閱讀
    EVA數據恢復—EVA存儲中<b class='flag-5'>磁盤</b>掉線<b class='flag-5'>導致</b>LUN丟失的數據恢復案例

    STM32G0B1RE 從SPI+DMA返回數據時開始3個字節錯誤的原因?怎么解決?

    的執行時間。通過MISO引腳可以看到前3個字節為0xF1,這3個字節實際上為上一SPI通訊的末尾3字節,后面的"0x01 0x0
    發表于 04-07 06:20

    如何讀取ST25DV04后256個字節

    當前正在開發安卓APP,碰到無法讀取后256個字節數據的問題, 手機端發送命令如下 0x02, 0x23, 0x40, 0x7fST25DV04回復 0x01,0x0f可以看到是讀取失敗了,請問一下應該如何
    發表于 03-18 06:12

    FileX無法讀取超過512個字節的數據是什么原因導致的?

    使用的是FileX+LevelX+NorFlash,上電后,寫1K的數據,然后再讀,此時是正常的。但是當我注釋掉寫函數,重新燒錄,再讀之前的文件,只能讀到前512個字節,后面讀到的都是0.不知道是什么原因
    發表于 03-14 06:51

    使用i2c從從站讀取個字節時,為什么主站只發送一個字節后就發送NACK呢?

    當我使用 i2c 從從站讀取個字節時,有時會返回 RX_OVERFLOW。 我使用邏輯分析儀抓取總線波形,發現只接收到一個字節,主控器發出 NACK,之后返回錯誤代碼
    發表于 03-05 07:42

    spi讀取個字節的時候該怎么判斷UART的上一個字節已經讀完了?

    想問一下 spi 的 SPI_SpiIsBusBusy() 的這個API在 UART 中怎么實現,讀取個字節的時候該怎么判斷 UART 的上一個字節已經讀完了?
    發表于 02-02 06:54
    主站蜘蛛池模板: xxxx日本在线播放免费不卡 | 911精品国产91久久久久 | 九九热精品视频在线播放 | 激情综合视频 | 久久性久久性久久久爽 | 美女视频黄a视频美女大全 美女视频一区二区 | 久久久久久人精品免费费看 | 色国产视频 | 丁香婷婷亚洲 | 欧美另类bbw | 99久久免费中文字幕精品 | 爱爱免费视频 | h在线免费 | 午夜免费福利片观看 | 国产精品热久久毛片 | 色综合久久98天天综合 | 国产午夜精品一区二区三区 | xxx亚洲日本 | 手机在线1024 | 精品国产你懂的在线观看 | 两性色午夜视频自由成熟的性 | 亚洲成网777777国产精品 | 黄色天天影视 | 成人在线一区二区三区 | 亚洲日本高清 | 丁香伊人五月综合激激激 | 色噜噜狠狠狠色综合久 | 亚洲午夜一区二区三区 | 国内一区二区 | 国产激爽大片在线播放 | 丁香综合激情 | 免费看男女下面日出水视频 | 一级毛片子 | 日韩三级| 免费aa| 思思久久96热在精品不卡 | 亚洲一区二区三区四区在线 | 亚洲国产福利精品一区二区 | 在线视频久久 | 久爱综合| 色色视频免费网 |