淺淡Linux的IO和磁盤IO的檢測
IO的分類
文件讀寫方式的各種差異,導致 I/O 的分類多種多樣。最常見的有,
- 緩沖與非緩沖 I/O。根據是否使用了標準庫的緩存接口,自己編寫的緩存等:
1.緩沖 I/O,是指利用標準庫緩存來加速文件的訪問,而標準庫內部再通過系統調度訪問文件。
2.非緩沖 I/O,是指直接通過系統調用來訪問文件,不再經過標準庫緩存。
- 直接與非直接 I/O。根據是否使用了內核的緩存。使用內核緩存的是非直接io。open系統調用O_DIRECT參數:
1.直接 I/O,是指跳過操作系統的頁緩存,直接跟文件系統交互來訪問文件。
2.非直接 I/O 正好相反,文件讀寫時,先要經過系統的頁緩存,然后再由內核或額外的系統調用,真正寫入磁盤。
- 同步的阻塞與非阻塞 I/O。根據應用程序是否阻塞自身運行,可以把文件 I/O 分為阻塞 I/O 和非阻塞 I/O:
1.阻塞 I/O,是指應用程序執行 I/O 操作后,如果沒有獲得響應,就會阻塞當前線程,自然就不能執行其他任務。
2.非阻塞 I/O,是指應用程序執行 I/O 操作后,不會阻塞當前的線程,而會立刻返回。設置 O_NONBLOCK 標志,就表示用非阻塞方式訪問,可以繼續執行其他的任務,隨后再通過輪詢或者事件通知的形式,獲取調用的結果。嚴格講是把阻塞點的位置換了(select,poll,epoll等)。主要是使用在標準輸出和網絡上。
- 同步與異步 I/O 。根據是否等待響應結果,可以把文件 I/O 分為同步和異步 I/O:
1.同步 I/O,是指應用程序執行 I/O 操作后,要一直等到整個 I/O 完成后,才能獲得 I/O 響應。
2.異步 I/O,是指應用程序執行 I/O 操作后,不用等待完成和完成后的響應,而是繼續執行就可以。等到這次 I/O 完成后,響應會用事件通知的方式,告訴應用程序。
Linux上的文件系統 I/O
進程要想往文件系統里面讀寫數據,需要很多層的組件一起合作。具體是怎么合作的呢?我們一起來看一看。
在應用層,進程在進行文件讀寫操作時,可通過系統調用如 sys_open、sys_read、sys_write 等。在內核,每個進程都需要為打開的文件,維護一定的數據結構。在內核,整個系統打開的文件,也需要維護一定的數據結構。

通用塊層
通用塊層是一個內核組件,它處理來自系統中的所有塊設備的請求。
- 將數據從磁盤映射到內存中。僅當cpu訪問數據時,才將頁框映射為內核中的線性地址中,并在數據訪問結束時取消映射。
- 通過一些附件手段,如DMA等,實現一個“零-拷貝”模式,將磁盤數據直接存放在用戶態的地址空間中而不是首先復制到內核地址空間。因為,內核為I/O數據傳送使用的緩沖區所在的葉框就映射在進程的用戶態線性地址中。
- 管理邏輯卷,例如LVM和RAID(軟件RAID)使用的邏輯卷。
通用塊層是 Linux 磁盤 I/O 的核心。向上,它為文件系統和應用程序,提供訪問了塊設備的標準接口;向下,把各種異構的磁盤設備,抽象為統一的塊設備,并會對文件系統和應用程序發來的 I/O 請求進行重新排序、請求合并等,提高了磁盤訪問的效率。
I/O調度程序層
事實上,Linux 內核支持四種 I/O 調度算法,分別是 NOOP、CFQ 、DeadLine與Anticipatory。這里我也分別介紹一下。
第一種 NOOP ,也被稱為電梯算法。是最簡單的一種 I/O 調度算法。它實際上是一個先入先出的隊列,只做一些最基本的請求合并,常用于 SSD 磁盤。
第二種 CFQ(Completely Fair Scheduler),也被稱為完全公平調度器,是現在很多發行版的默認 I/O 調度器,它為每個進程維護了一個 I/O 調度隊列,并按照時間片來均勻分布每個進程的 I/O 請求。
類似于進程 CPU 調度,CFQ 還支持進程 I/O 的優先級調度,所以它適用于運行大量進程的系統,像是桌面環境、多媒體應用等。
第三種 DeadLine 最后期限調度算法。使用了四個隊列。其中兩個排序隊列分別包含讀和寫請求,其中的請求是根據起始扇區排序的。另外兩個最后期限隊列包含了相同的讀和寫請求,但是這是根據它們的最后期限排隊的。可以提高機械磁盤的吞吐量,并確保達到最終期限(deadline)的請求被優先處理。此算法在全局吞吐量和延遲方面做了權衡,犧牲了一定的全局吞吐量來避免饑餓請求的可能。當系統存在大量順序I/O請求的時候,此算法可能導致I/O請求無法被很好的排序,引發頻繁尋道。
第四種 Anticipatory 預期算法。借用了“最后期限調度算法”的基本機制:兩個最后期限隊列和兩個排序隊列,I/O調度程序在讀和寫請求之間交互掃描排序隊列,不過更傾向于讀請求。掃描基本是連續的,除非有某個請求超時。為每個讀IO都設置了大約7ms的等待時間窗口。如果在這7ms內OS收到了相鄰位置的讀IO請求,就可以立即滿足。為了滿足隨機IO和順序IO混合的場景,此算法適合寫入較多的環境,不適合MySQL等隨機讀取較多的數據庫環境。
磁盤IO檢測
在磁盤測試中最關心的幾個指標分別為:
- iops(每秒執行的IO次數)、bw(帶寬,每秒的吞吐量)、lat(每次IO操作的延遲)
- 當每次IO操作的block較小時,如512bytes/4k/8k等,測試的主要是iops
- 當每次IO操作的block較大時,如256k/512k/1M等,測試的主要是bw
使用fio工具來進行磁盤io檢測
1. FIO 簡介
FIO 是一款 用于對磁盤進行性能測試的工具。可以測試IOPS,吞吐量,IO延遲等主要性能指標。而且支持多種IO引擎。
2. FIO 下載
下載地址:http://brick.kernel.dk/snaps/
打開以上網址,選擇自己需要的版本并下載。比如:
- wget http://brick.kernel.dk/snaps/fio-3.5.tar.gz
3. 解壓并安裝
- # tar -xzvf ./fio-3.5.tar.gz
- .... 省略輸出
- # cd fio-3.5
- # make && make install
- .... 省略輸出# which fio
- /usr/local/bin/fio
4. 使用說明
- filename=/dev/sdb1 測試文件名稱,通常選擇需要測試的盤的data目錄。
- direct=1 測試過程繞過機器自帶的buffer。使測試結果更真實。
- rw=randwrite 測試隨機寫的I/O
- rw=randrw 測試隨機寫和讀的I/O
- bs=16k 單次io的塊文件大小為16k
- bsrange=512-2048 同上,指定數據塊的大小范圍
- size=5g 本次的測試文件大小為5g,以每次4k的io進行測試。
- numjobs=30 本次的測試線程為30.
- runtime=1000 測試時間為1000秒,如果不寫則一直將5g文件分4k每次寫完為止。
- ioengine=psync io引擎使用pync方式
- rwmixwrite=30 在混合讀寫的模式下,寫占30%
- group_reporting 關于顯示結果的,匯總每個進程的信息
- lockmem=1g 只使用1g內存進行測試。
- zero_buffers 用0初始化系統buffer。
- nrfiles=8 每個進程生成文件的數量
5. 測試示例
- 混合測試:
- fio -filename=/tmp/test -direct=1 -iodepth 1 -thread -rw=randrw -rwmixread=70 -ioengine=psync -bs=512b -size=200m -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 順序讀:
- fio -filename=/dev/test -direct=1 -iodepth 1 -thread -rw=read -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 隨機寫:
- fio -filename=/dev/test -direct=1 -iodepth 1 -thread -rw=randwrite -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
- 順序寫:
- fio -filename=/dev/test -direct=1 -iodepth 1 -thread -rw=write -ioengine=psync -bs=16k -size=2G -numjobs=10 -runtime=60 -group_reporting -name=mytest
6. IO讀寫測試參考腳本
- https://github.com/sunsharing-note/fio_test.git
本文轉載自微信公眾號「運維開發故事」,可以通過以下二維碼關注。轉載本文請聯系運維開發故事眾號。