導航:首頁 > 編程系統 > linux系統io

linux系統io

發布時間:2023-06-12 20:19:51

1. linux 磁碟IO

磁碟結構與數據存儲方式, 數據是如何存儲的,又通過怎樣的方式被訪問?

機械硬碟主要由磁碟碟片、磁頭、主軸與傳動軸等組成;數據就存放在磁碟碟片中

現代硬碟尋道都是採用CHS( Cylinder Head Sector )的方式,硬碟讀取數據時,讀寫磁頭沿徑向移動,移到要讀取的扇區所在磁軌的上方,這段時間稱為 尋道時間(seek time) 因讀寫磁頭的起始位置與目標位置之間的距離不同,尋道時間也不同 。磁頭到達指定磁軌後,然後通過碟片的旋轉,使得要讀取的扇區轉到讀寫磁頭的下方,這段時間稱為 旋轉延遲時間(rotational latencytime) 。然後再讀寫數據,讀寫數據也需要時間,這段時間稱為 傳輸時間(transfer time)

固態硬碟主要由主控晶元、快閃記憶體顆粒與緩存組成;數據就存放在快閃記憶體晶元中
通過主控晶元進行定址, 因為是電信號方式, 沒有任何物理結構, 所以定址速度非常快且與數據存儲位置無關

如何查看系統IO狀態

查看磁碟空間

調用 open , fwrite 時到底發生了什麼?

在一個IO過程中,以下5個API/系統調用是必不可少的
Create 函數用來打開一個文件,如果該文件不存在,那麼需要在磁碟上創建該文件
Open 函數用於打開一個指定的文件。如果在 Open 函數中指定 O_CREATE 標記,那麼 Open 函數同樣可以實現 Create 函數的功能
Clos e函數用於釋放文件句柄
Write 和 Read 函數用於實現文件的讀寫過程

O_SYNC (先寫緩存, 但是需要實際落盤之後才返回, 如果接下來有讀請求, 可以從內存讀 ), write-through
O_DSYNC (D=data, 類似O_SYNC, 但是只同步數據, 不同步元數據)
O_DIRECT (直接寫盤, 不經過緩存)
O_ASYNC (非同步IO, 使用信號機制實現, 不推薦, 直接用aio_xxx)
O_NOATIME (讀取的時候不更新文件 atime(access time))

sync() 全局緩存寫回磁碟
fsync() 特定fd的sync()
fdatasync() 只刷數據, 不同步元數據

mount noatime(全局不記錄atime), re方式(只讀), sync(同步方式)

一個IO的傳奇一生 這里有一篇非常好的資料,講述了整個IO過程;
下面簡單記錄下自己的理解的一次常見的Linux IO過程, 想了解更詳細及相關源碼,非常推薦閱讀上面的原文

Linux IO體系結構

[站外圖片上傳中...(image-38a7b-1644137945193)]

Superblock 超級描述了整個文件系統的信息。為了保證可靠性,可以在每個塊組中對superblock進行備份。為了避免superblock冗餘過多,可以採用稀疏存儲的方式,即在若干個塊組中對superblock進行保存,而不需要在所有的塊組中都進行備份
GDT 組描述符表 組描述符表對整個組內的數據布局進行了描述。例如,數據塊點陣圖的起始地址是多少?inode點陣圖的起始地址是多少?inode表的起始地址是多少?塊組中還有多少空閑塊資源等。組描述符表在superblock的後面
數據塊點陣圖 數據塊點陣圖描述了塊組內數據塊的使用情況。如果該數據塊已經被某個文件使用,那麼點陣圖中的對應位會被置1,否則該位為0
Inode點陣圖 Inode點陣圖描述了塊組內inode資源使用情況。如果一個inode資源已經使用,那麼對應位會被置1
Inode表 (即inode資源)和數據塊。這兩塊占據了塊組內的絕大部分空間,特別是數據塊資源

一個文件是由inode進行描述的。一個文件佔用的數據塊block是通過inode管理起來的 。在inode結構中保存了直接塊指針、一級間接塊指針、二級間接塊指針和三級間接塊指針。對於一個小文件,直接可以採用直接塊指針實現對文件塊的訪問;對於一個大文件,需要採用間接塊指針實現對文件塊的訪問

最簡單的調度器。它本質上就是一個鏈表實現的 fifo 隊列,並對請求進行簡單的 合並 處理。
調度器本身並沒有提供任何可以配置的參數

讀寫請求被分成了兩個隊列, 一個用訪問地址作為索引,一個用進入時間作為索引,並且採用兩種方式將這些request管理起來;
在請求處理的過程中,deadline演算法會優先處理那些訪問地址臨近的請求,這樣可以最大程度的減少磁碟抖動的可能性。
只有在有些request即將被餓死的時候,或者沒有辦法進行磁碟順序化操作的時候,deadline才會放棄地址優先策略,轉而處理那些即將被餓死的request

deadline演算法可調整參數
read_expire : 讀請求的超時時間設置(ms)。當一個讀請求入隊deadline的時候,其過期時間將被設置為當前時間+read_expire,並放倒fifo_list中進行排序
write_expire :寫請求的超時時間設置(ms)
fifo_batch :在順序(sort_list)請求進行處理的時候,deadline將以batch為單位進行處理。每一個batch處理的請求個數為這個參數所限制的個數。在一個batch處理的過程中,不會產生是否超時的檢查,也就不會產生額外的磁碟尋道時間。這個參數可以用來平衡順序處理和飢餓時間的矛盾,當飢餓時間需要盡可能的符合預期的時候,我們可以調小這個值,以便盡可能多的檢查是否有飢餓產生並及時處理。增大這個值當然也會增大吞吐量,但是會導致處理飢餓請求的延時變長
writes_starved :這個值是在上述deadline出隊處理第一步時做檢查用的。用來判斷當讀隊列不為空時,寫隊列的飢餓程度是否足夠高,以時deadline放棄讀請求的處理而處理寫請求。當檢查存在有寫請求的時候,deadline並不會立即對寫請求進行處理,而是給相關數據結構中的starved進行累計,如果這是第一次檢查到有寫請求進行處理,那麼這個計數就為1。如果此時writes_starved值為2,則我們認為此時飢餓程度還不足夠高,所以繼續處理讀請求。只有當starved >= writes_starved的時候,deadline才回去處理寫請求。可以認為這個值是用來平衡deadline對讀寫請求處理優先順序狀態的,這個值越大,則寫請求越被滯後處理,越小,寫請求就越可以獲得趨近於讀請求的優先順序
front_merges :當一個新請求進入隊列的時候,如果其請求的扇區距離當前扇區很近,那麼它就是可以被合並處理的。而這個合並可能有兩種情況,一個是向當前位置後合並,另一種是向前合並。在某些場景下,向前合並是不必要的,那麼我們就可以通過這個參數關閉向前合並。默認deadline支持向前合並,設置為0關閉

在調度一個request時,首先需要選擇一個一個合適的cfq_group。Cfq調度器會為每個cfq_group分配一個時間片,當這個時間片耗盡之後,會選擇下一個cfq_group。每個cfq_group都會分配一個vdisktime,並且通過該值採用紅黑樹對cfq_group進行排序。在調度的過程中,每次都會選擇一個vdisktime最小的cfq_group進行處理。
一個cfq_group管理了7棵service tree,每棵service tree管理了需要調度處理的對象cfq_queue。因此,一旦cfq_group被選定之後,需要選擇一棵service tree進行處理。這7棵service tree被分成了三大類,分別為RT、BE和IDLE。這三大類service tree的調度是按照優先順序展開的

通過優先順序可以很容易的選定一類Service tree。當一類service tree被選定之後,採用service time的方式選定一個合適的cfq_queue。每個Service tree是一棵紅黑樹,這些紅黑樹是按照service time進行檢索的,每個cfq_queue都會維護自己的service time。分析到這里,我們知道,cfq演算法通過每個cfq_group的vdisktime值來選定一個cfq_group進行服務,在處理cfq_group的過程通過優先順序選擇一個最需要服務的service tree。通過該Service tree得到最需要服務的cfq_queue。該過程在 cfq_select_queue 函數中實現

一個cfq_queue被選定之後,後面的過程和deadline演算法有點類似。在選擇request的時候需要考慮每個request的延遲等待時間,選擇那種等待時間最長的request進行處理。但是,考慮到磁碟抖動的問題,cfq在處理的時候也會進行順序批量處理,即將那些在磁碟上連續的request批量處理掉

cfq調度演算法的參數
back_seek_max :磁頭可以向後定址的最大范圍,默認值為16M
back_seek_penalty :向後定址的懲罰系數。這個值是跟向前定址進行比較的

fifo_expire_async :設置非同步請求的超時時間。同步請求和非同步請求是區分不同隊列處理的,cfq在調度的時候一般情況都會優先處理同步請求,之後再處理非同步請求,除非非同步請求符合上述合並處理的條件限制范圍內。當本進程的隊列被調度時,cfq會優先檢查是否有非同步請求超時,就是超過fifo_expire_async參數的限制。如果有,則優先發送一個超時的請求,其餘請求仍然按照優先順序以及扇區編號大小來處理
fifo_expire_sync :這個參數跟上面的類似,區別是用來設置同步請求的超時時間
slice_idle :參數設置了一個等待時間。這讓cfq在切換cfq_queue或service tree的時候等待一段時間,目的是提高機械硬碟的吞吐量。一般情況下,來自同一個cfq_queue或者service tree的IO請求的定址局部性更好,所以這樣可以減少磁碟的定址次數。這個值在機械硬碟上默認為非零。當然在固態硬碟或者硬RAID設備上設置這個值為非零會降低存儲的效率,因為固態硬碟沒有磁頭定址這個概念,所以在這樣的設備上應該設置為0,關閉此功能
group_idle :這個參數也跟上一個參數類似,區別是當cfq要切換cfq_group的時候會等待一段時間。在cgroup的場景下,如果我們沿用slice_idle的方式,那麼空轉等待可能會在cgroup組內每個進程的cfq_queue切換時發生。這樣會如果這個進程一直有請求要處理的話,那麼直到這個cgroup的配額被耗盡,同組中的其它進程也可能無法被調度到。這樣會導致同組中的其它進程餓死而產生IO性能瓶頸。在這種情況下,我們可以將slice_idle = 0而group_idle = 8。這樣空轉等待就是以cgroup為單位進行的,而不是以cfq_queue的進程為單位進行,以防止上述問題產生
low_latency :這個是用來開啟或關閉cfq的低延時(low latency)模式的開關。當這個開關打開時,cfq將會根據target_latency的參數設置來對每一個進程的分片時間(slice time)進行重新計算。這將有利於對吞吐量的公平(默認是對時間片分配的公平)。關閉這個參數(設置為0)將忽略target_latency的值。這將使系統中的進程完全按照時間片方式進行IO資源分配。這個開關默認是打開的

target_latency :當low_latency的值為開啟狀態時,cfq將根據這個值重新計算每個進程分配的IO時間片長度
quantum :這個參數用來設置每次從cfq_queue中處理多少個IO請求。在一個隊列處理事件周期中,超過這個數字的IO請求將不會被處理。這個參數只對同步的請求有效
slice_sync :當一個cfq_queue隊列被調度處理時,它可以被分配的處理總時間是通過這個值來作為一個計算參數指定的。公式為: time_slice = slice_sync + (slice_sync/5 * (4 - prio)) 這個參數對同步請求有效
slice_async :這個值跟上一個類似,區別是對非同步請求有效
slice_async_rq :這個參數用來限制在一個slice的時間范圍內,一個隊列最多可以處理的非同步請求個數。請求被處理的最大個數還跟相關進程被設置的io優先順序有關

通常在Linux上使用的IO介面是同步方式的,進程調用 write / read 之後會阻塞陷入到內核態,直到本次IO過程完成之後,才能繼續執行,下面介紹的非同步IO則沒有這種限制,但是當前Linux非同步IO尚未成熟

目前Linux aio還處於較不成熟的階段,只能在 O_DIRECT 方式下才能使用(glibc_aio),也就是無法使用默認的Page Cache機制

正常情況下,使用aio族介面的簡要方式如下:

io_uring 是 2019 年 5 月發布的 Linux 5.1 加入的一個重大特性 —— Linux 下的全新的非同步 I/O 支持,希望能徹底解決長期以來 Linux AIO 的各種不足
io_uring 實現非同步 I/O 的方式其實是一個生產者-消費者模型:

邏輯卷管理
RAID0
RAID1
RAID5(糾錯)
條帶化

Linux系統性能調整:IO過程
Linux的IO調度
一個IO的傳奇一生
理解inode
Linux 文件系統是怎麼工作的?
Linux中Buffer cache性能問題一探究竟
Asynchronous I/O and event notification on linux
AIO 的新歸宿:io_uring
Linux 文件 I/O 進化史(四):io_uring —— 全新的非同步 I/O

2. linux中的io操作指的是什麼

計算機中的I/O匯流排(輸入輸出匯流排),主要用於聯系硬碟、USB、網卡等介面設備,和這些設備的數據「交流」(讀與寫),就可以叫做I/O操作。

3. linux中的io操作指的是什麼

吞吐量是指對網路、設備、埠、虛電路或其他設施,單位時間內成功地傳送數據的數量(以比特、位元組、分組等測量)。IO吞吐量顧名思義即單位時間內成功讀寫數據的數量。

問題帖圖中使用了iostat命令,輸出信息的意義如下 :
tps:該設備每秒的傳輸次數(Indicate the number of transfers per second that were issued to the device.)。"一次傳輸"意思是"一次I/O請求"。多個邏輯請求可能會被合並為"一次I/O請求"。"一次傳輸"請求的大小是未知的。

kB_read/s:每秒從設備(drive expressed)讀取的數據量;
kB_wrtn/s:每秒向設備(drive expressed)寫入的數據量;
kB_read:讀取的總數據量;
kB_wrtn:寫入的總數量數據量;這些單位都為Kilobytes。

4. 在linux系統中如何查看cpu和io

在 Linux 系統中,可以使用以下命令查看 CPU 信息:

5. 如何提高Linux伺服器磁碟io性能

您好,很高興為您解答。

在現有文件系統下進行優化:
linux內核和各個文件系統採用了幾個優化方案來提升磁碟訪問速度。但這些優化方案需要在我們的伺服器設計中進行配合才能得到充分發揮。
文件系統緩存
linux內核會將大部分空閑內存交給虛擬文件系統,來作為文件緩存,叫做page cache。在內存不足時,這部分內存會採用lru演算法進行淘汰。通過free命令查看內存,顯示為cached的部分就是文件緩存了。

如何針對性優化:
lru並不是一個優秀淘汰演算法,lru最大的優勢是普適性好,在各種使用場景下都能起到一定的效果。如果能找到當前使用場景下,文件被訪問的統計特徵,針 對性的寫一個淘汰演算法,可以大幅提升文件緩存的命中率。對於http正向代理來說,一個好的淘汰演算法可以用1GB內存達到lru演算法100GB內存的緩存 效果。如果不打算寫一個新的淘汰演算法,一般不需要在應用層再搭一個文件cache程序來做緩存。

最小分配:
當文件擴大,需要分配磁碟空間時,大部分文件系統不會僅僅只分配當前需要的磁碟空間,而是會多分配一些磁碟空間。這樣下次文件擴大時就可以使用已經分配好的空間,而不會頻繁的去分配新空間。
例如ext3下,每次分配磁碟空間時,最小是分配8KB。
最小分配的副作用是會浪費一些磁碟空間(分配了但是又沒有使用)

如何針對性優化:
我們在reiserfs下將最小分配空間從8KB改大到128K後提升了30%的磁碟io性能。如果當前使用場景下小文件很多,把預分配改大就會浪費很多 磁碟空間,所以這個數值要根據當前使用場景來設定。似乎要直接改源代碼才能生效,不太記得了,09年的時候改的,有興趣的同學自己google吧。

io訪問調度:
在同時有多個io訪問時,linux內核可以對這些io訪問按LBA進行合並和排序,這樣磁頭在移動時,可以「順便」讀出移動過程中的數據。
SATA等磁碟甚至在磁碟中內置了io排序來進一步提升性能,一般需要在主板中進行配置才能啟動磁碟內置io排序。linux的io排序是根據LBA進行的,但LBA是一個一維線性地址,無法完全反應出二維的圓形磁碟,所以磁碟的內置io排序能達到更好的效果。

如何針對性優化:
io訪問調度能大幅提升io性能,前提是應用層同時發起了足夠的io訪問供linux去調度。
怎樣才能從應用層同時向內核發起多個io訪問呢?
方案一是用aio_read非同步發起多個文件讀寫請求。
方案二是使用磁碟線程池同時發起多個文件讀寫請求。
對我們的http正向代理來說,採用16個線程讀寫磁碟可以將性能提升到2.5倍左右。具體開多少個線程/進程,可以根據具體使用場景來決定。

小提示:
將文件句柄設置為非阻塞時,進程還是會睡眠等待磁碟io,非阻塞對於文件讀寫是不生效的。在正常情況下,讀文件只會引入十幾毫秒睡眠,所以不太明顯;而在磁碟io極大時,讀文件會引起十秒以上的進程睡眠。

預讀取:
linux內核可以預測我們「將來的讀請求」並提前將數據讀取出來。通過預讀取可以減少讀io的次數,並且減小讀請求的延時。

如何針對性優化:
預讀取的預測准確率是有限的,與其依賴預讀取,不如我們直接開一個較大的緩沖區,一次性將文件讀出來再慢慢處理;盡量不要開一個較小的緩沖區,循環讀文件/處理文件。
雖然說「預讀取」和「延遲分配」能起到類似的作用,但是我們自己擴大讀寫緩沖區效果要更好。

延遲分配:
當文件擴大,需要分配磁碟空間時,可以不立即進行分配,而是暫存在內存中,將多次分配磁碟空間的請求聚合在一起後,再進行一次性分配。
延遲分配的目的也是減少分配次數,從而減少文件不連續。

延遲分配的副作用有幾個:
1、如果應用程序每次寫數據後都通過fsync等介面進行強制刷新,延遲分配將不起作用
2、延遲分配有可能間歇性引入一個較大的磁碟IO延時(因為要一次性向磁碟寫入較多數據)
只有少數新文件系統支持這個特性

如何針對性優化:
如果不是對安全性(是否允許丟失)要求極高的數據,可以直接在應用程序里緩存起來,積累到一定大小再寫入,效果比文件系統的延遲分配更好。如果對安全性要求極高,建議經常用fsync強制刷新。

在線磁碟碎片整理:
Ext4提供了一款碎片整理工具,叫e4defrag,主要包含三個功能:
1、讓每個文件連續存儲
2、盡量讓每個目錄下的文件連續存儲
3、通過整理空閑磁碟空間,讓接下來的分配更不容易產生碎片

如何針對性優化:
「讓每個目錄下的文件連續存儲」是一個極有價值的功能。
傳統的做法是通過拼接圖片來將這10張圖片合並到一張大圖中,再由前端將大圖切成10張小圖。
有了e4defrag後,可以將需連續訪問的文件放在同一個文件夾下,再定期使用e4defrag進行磁碟整理。

實現自己的文件系統:
在大部分伺服器上,不需要支持「修改文件」這個功能。一旦文件創建好,就不能再做修改操作,只支持讀取和刪除。在這個前提下,我們可以消滅所有文件碎片,把磁碟io效率提升到理論極限。

有一個公式可以衡量磁碟io的效率:
磁碟利用率 = 傳輸時間/(平均尋道時間+傳輸時間)

如若滿意,請點擊回答右側【採納答案】,如若還有問題,請點擊【追問】

~ O(∩_∩)O~

6. 如何找出Linux系統高IO的思路總結

前言

I/O Wait是一個需要使用高級的工具來debug問題原因,當然也有許多基本工具的高級用法。I/O wait的問題難以定位的原因是:因為我們有很多工具可以告訴你I/O 受限了,但是並沒有告訴你具體是哪個進程引起的。

1. 如何確認,是否是I/O問題導致系統緩慢

確認是否是I/O導致的系統緩慢我們可以使用多個命令,但是,最簡單的是unix的命令 top

# top

top - 14:31:20 up 35 min, 4 users, load average: 2.25, 1.74, 1.68

Tasks: 71 total, 1 running, 70 sleeping, 0 stopped, 0 zombie

Cpu(s): 2.3%us, 1.7%sy, 0.0%ni, 0.0%id, 96.0%wa, 0.0%hi, 0.0%si, 0.0%st

Mem: 245440k total, 241004k used, 4436k free, 496k buffers

Swap: 409596k total, 5436k used, 404160k free, 182812k cached

從CPU這行,可以發現CPU的io wait;這里是96.0%。越高就代表CPU用於io wait的資源越多。

2. 找出哪個磁碟正在被寫入

上邊的top命令從一個整體上說明了I/O wait,但是並沒有說明是哪塊磁碟影響的,想知道是哪塊磁碟引發的問題,可以使用另外一個命令 iostat 命令

$ iostat -x 2 5

avg-cpu: %user %nice %system %iowait %steal %idle

  3.66 0.00 47.64 48.69 0.00 0.00

Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util

sda 44.50 39.27 117.28 29.32 11220.94 13126.70 332.17 65.77 462.79 9.80 2274.71 7.60 111.41

dm-0 0.00 0.00 83.25 9.95 10515.18 4295.29 317.84 57.01 648.54 16.73 5935.79 11.48 107.02

dm-1 0.00 0.00 57.07 40.84 228.27 163.35 8.00 93.84 979.61 13.94 2329.08 10.93 107.02

iostat 會每2秒更新一次,一共列印5次信息, -x 的選項是列印出擴展信息

第一個iostat 報告會列印出系統最後一次啟動後的統計信息,這也就是說,在多數情況下,第一個列印出來的信息應該被忽略,剩下的報告,都是基於上一次間隔的時間。舉例子來說,這個命令會列印5次,第二次的報告是從第一次報告出來一個後的統計信息,第三次是基於第二次 ,依次類推

所以,一定記住:第一個忽略!

在上面的例子中,sda的%utilized 是111.41%,這個很好的說明了有進程正在寫入到sda磁碟中。

除了%utilized 外,我們可以從iostat得到更加豐富的資源信息,例如每毫秒讀寫請求(rrqm/s & wrqm/s)),每秒讀寫的((r/s & w/s)。在上邊的例子中,我們的項目看起來正在讀寫非常多的信息。這個對我們查找相應的進程非常有用。

3. 找出導致高IO的進程

# iotop

Total DISK READ: 8.00 M/s | Total DISK WRITE: 20.36 M/s

  TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND

15758 be/4 root 7.99 M/s 8.01 M/s 0.00 % 61.97 % bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

最簡單的方法就是用iotop找出哪個進程用了最多的存儲資源,從上面可以看到是bonnie++。

iotop很好用,但是不是默認安裝的。

如果沒有iotop,下面的方式也可以讓你有種方法縮小范圍,盡快找到是哪個進程。

ps 命令對內存和CPU有一個統計,但是他沒有對磁碟I/O的統計,雖然他沒有顯示磁碟I/O,但是它顯示進行的狀態,我們可以用來知道一個進程是否正在等待I/O

主要的進程狀態有:

PROCESS STATE CODES

D uninterruptible sleep (usually IO)

R running or runnable (on run queue)

S interruptible sleep (waiting for an event to complete)

T stopped, either by a job control signal or because it is being traced.

W paging (not valid since the 2.6.xx kernel)

X dead (should never be seen)

Z defunct ("zombie") process, terminated but not reaped by its parent.

等待I/O的進程的狀態一般是「uninterruptible sleep」,或者「D」,我們可以很容易的查找到正在等待I/O的進程

# for x in `seq 1 1 10`; do ps -eo state,pid,cmd | grep "^D"; echo "----"; sleep 5; done

D 248 [jbd2/dm-0-8]

D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

----

D 22 [kswapd0]

D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

----

D 22 [kswapd0]

D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

----

D 22 [kswapd0]

D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

----

D 16528 bonnie++ -n 0 -u 0 -r 239 -s 478 -f -b -d /tmp

上邊的例子會循環的輸出狀態是D的進程,每5秒一次,一共10次

從輸出我們可以知道 bonnie++ 的pid是16528 ,在waiting,bonnie++看起來就是我們想找到的進程,但是,只是從它的狀態,我們沒有辦法證明就是bonnie++引起的I/O等待。

為了證明,我們可以可以查看/proc,每個進程目錄下都有一個叫io的文件,里邊保存這和iotop類似的信息。

# cat /proc/16528/io

rchar: 48752567

wchar: 549961789

syscr: 5967

syscw: 67138

read_bytes: 49020928

write_bytes: 549961728

cancelled_write_bytes: 0

read_bytes和write_bytes是這個進程從磁碟讀寫的位元組,在這個例子中,bonnie++進程讀取了46M的數據並且寫入了524MB的數據到磁碟上。

4. 找出哪個文件正在被大量寫入

lsof 命令可以展示一個進程打開的所有文件。從這個列表中,我們可以找到哪個文件被寫入。

# lsof -p 16528

COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME

bonnie++ 16528 root cwd DIR 252,0 4096 130597 /tmp

<truncated>

bonnie++ 16528 root 8u REG 252,0 501219328 131869 /tmp/Bonnie.16528

bonnie++ 16528 root 9u REG 252,0 501219328 131869 /tmp/Bonnie.16528

bonnie++ 16528 root 10u REG 252,0 501219328 131869 /tmp/Bonnie.16528

bonnie++ 16528 root 11u REG 252,0 501219328 131869 /tmp/Bonnie.16528

bonnie++ 16528 root 12u REG 252,0 501219328 131869 <strong>/tmp/Bonnie.16528</strong>

# df /tmp

Filesystem 1K-blocks Used Available Use% Mounted on

/dev/mapper/workstation-root 7667140 2628608 4653920 37% /

# pvdisplay

  --- Physical volume ---

  PV Name /dev/sda5

  VG Name workstation

  PV Size 7.76 GiB / not usable 2.00 MiB

  Allocatable yes

  PE Size 4.00 MiB

  Total PE 1986

  Free PE 8

  Allocated PE 1978

  PV UUID CLbABb-GcLB-l5z3-TCj3-IOK3-SQ2p-RDPW5S

使用pvdisplay可以看到,pv設備就是/dev/sda5,正是我們前面找到的sda。

參考文檔:http://bencane.com/2012/08/06/troubleshooting-high-io-wait-in-linux/

7. linux中block IO,no-block IO,非同步IO,IO多路復用筆記

        現在操作系統都是採用虛擬存儲器,那麼對32位操作系統而言,它的定址空間(虛擬存儲空間)為4G(2的32次方)。操作系統的核心是內核,獨立於普通的應用程序,可以訪問受保護的內存空間,也有訪問底層硬體設備的所有許可權。 為了保證用戶進程不能直接操作內核(kernel),保證內核的安全,操心系統將虛擬空間劃分為兩部分,一部分為內核空間,一部分為用戶空間 。針對linux操作系統而言, 將最高的1G位元組(從虛擬地址0xC0000000到0xFFFFFFFF) ,供內核使用,稱為內核空間, 而將較低的3G位元組(從虛擬地址0x00000000到0xBFFFFFFF),供各個進程使用,稱為用戶空間。

        文件描述符(File descriptor)是計算機科學中的一個術語,是一個用於表述 指向文件的引用的抽象化概念 。文件描述符在形式上是一個非負整數。 實際上,它是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表 。當程序打開一個現有文件或者創建一個新文件時,內核向進程返回一個文件描述符。在程序設計中,一些涉及底層的程序編寫往往會圍繞著文件描述符展開。但是文件描述符這一概念往往只適用於UNIX、Linux這樣的操作系統。

       剛才說了,對於一次IO訪問(以read舉例),數據會先被拷貝到操作系統內核的緩沖區中,然後才會從操作系統內核的緩沖區拷貝到應用程序的地址空間。所以說,當一個read操作發生時,它會經歷兩個階段:

1、等待數據准備 (Waiting for the data to be ready)

2、將數據從內核拷貝到進程中 (Copying the data from the kernel to the process)

正式因為這兩個階段,linux系統產生了下面 五種網路模式 的方案。

阻塞 I/O(blocking IO)

非阻塞 I/O(nonblocking IO)

I/O 多路復用( IO multiplexing)

非同步 I/O(asynchronous IO)

信號驅動 I/O( signal driven IO)

註:由於signal driven IO在實際中並不常用,所以我這只提及剩下的四種IO Model。

阻塞 I/O(blocking IO)

在linux中,默認情況下所有的socket都是blocking,一個典型的讀操作流程大概是這樣:

        當用戶進程調用了recvfrom這個系統調用,kernel就開始了IO的第一個階段:准備數據(對於網路IO來說,很多時候數據在一開始還沒有到達。比如,還沒有收到一個完整的UDP包。這個時候kernel就要等待足夠的數據到來)。這個過程需要等待,也就是說數據被拷貝到操作系統內核的緩沖區中是需要一個過程的。而在用戶進程這邊,整個進程會被阻塞(當然,是進程自己選擇的阻塞)。當kernel一直等到數據准備好了,它就會將數據從kernel中拷貝到用戶內存,然後kernel返回結果,用戶進程才解除block的狀態,重新運行起來。

所以,blocking IO的特點就是在IO執行的兩個階段都被block了(內核阻塞讀取數據,內核將數據復制到應用戶態)。

非阻塞 I/O(nonblocking IO)

linux下,可以通過設置socket使其變為non-blocking。當對一個non-blocking socket執行讀操作時,流程是這個樣子:

       當用戶進程發出read操作時,如果kernel中的數據還沒有準備好,那麼它並不會block用戶進程,而是立刻返回一個error。從用戶進程角度講 ,它發起一個read操作後,並不需要等待,而是馬上就得到了一個結果。用戶進程判斷結果是一個error時,它就知道數據還沒有準備好,於是它可以再次發送read操作。一旦kernel中的數據准備好了,並且又再次收到了用戶進程的system call,那麼它馬上就將數據拷貝到了用戶內存,然後返回。

所以,nonblocking IO的特點是用戶進程需要 不斷的主動詢問 kernel數據好了沒有( 內核讀取數據時,用戶態不需要阻塞,內核將數據復制到用戶態時,需要阻塞 )。

I/O 多路復用( IO multiplexing)

         IO multiplexing就是我們說的select,poll,epoll,有些地方也稱這種IO方式為event driven IO。select/epoll的好處就在於單個process就可以同時處理多個網路連接的IO。它的基本原理就是 select,poll,epoll這個function會不斷的輪詢所負責的所有socket ,當某個socket有數據到達了,就通知用戶進程。

        當用戶 進程調用了select , 那麼整個進程會被block ,而同時,kernel會「監視」所有 select負責的socket(一個管理多個socket連接),當任何一個socket中的數據准備好了,select就會返回 。這個時候用戶進程再調用read操作, 將數據從kernel拷貝到用戶進程 。

所以,I/O 多路復用的特點是通過一種機制一個進程能同時等待多個文件描述符,而這些文件描述符(套接字描述符)其中的任意一個進入讀就緒狀態,select()函數就可以返回。

這個圖和blocking IO的圖其實並沒有太大的不同,事實上,還更差一些。 因為這里需要使用兩個system call (select 和 recvfrom),而blocking IO只調用了一個system call (recvfrom) 。但是,用select的優勢在於它可以同時處理多個connection。

所以,如果處理的 連接數不是很高的話,使用select/epoll的web server不一定比使用multi-threading + blocking IO的web server性能更好,可能延遲還更大 。select/epoll的優勢並不是對於單個連接能處理得更快,而是在於能處理更多的連接。)

在IO multiplexing Model中,實際中,對於每一個socket,一般都設置成為non-blocking,但是,如上圖所示,整個用戶的process其實是一直被block的。只不過process是被select這個函數block,而不是被socket IO給block。

總結:IO多路復用其實也是阻塞的,阻塞的地方在用當有socket連接有數據以後, 會阻塞知道數據從內核復制到用戶態(第二步阻塞)。

非同步 I/O(asynchronous IO)

inux下的asynchronous IO其實用得很少。先看一下它的流程:

        用戶進程發起read操作之後,立刻就可以開始去做其它的事。而另一方面,從kernel的角度,當它受到一個asynchronous read之後,首先它會立刻返回,所以不會對用戶進程產生任何block。然後,kernel會等待數據准備完成,然後將數據拷貝到用戶內存,當這一切都完成之後,kernel會給用戶進程發送一個signal,告訴它read操作完成了。

總結:兩個階段都不需要用戶進程干涉,內核將數據准備好以後通知用戶態去讀取

總結

blocking和non-blocking的區別

調用blocking IO會一直block住對應的進程直到操作完成,而non-blocking IO在kernel還准備數據的情況下會立刻返回。

synchronous IO和asynchronous IO的區別

在說明synchronous IO和asynchronous IO的區別之前,需要先給出兩者的定義。POSIX的定義是這樣子的:

- A synchronous I/O operation causes the requesting process to be blocked until that I/O operation completes;

- An asynchronous I/O operation does not cause the requesting process to be blocked;

兩者的區別就在於synchronous IO做」IO operation」的時候會將process阻塞。按照這個定義,之前所述的 blocking IO,non-blocking IO,IO multiplexing都屬於synchronous IO 。

       有人會說,non-blocking IO並沒有被block啊。這里有個非常「狡猾」的地方,定義中所指的」IO operation」是指真實的IO操作,就是例子中的recvfrom這個system call。non-blocking IO在執行recvfrom這個system call的時候,如果kernel的數據沒有準備好,這時候不會block進程。但是, 當kernel中數據准備好的時候,recvfrom會將數據從kernel拷貝到用戶內存中,這個時候進程是被block了,在這段時間內,進程是被block的。

而asynchronous IO則不一樣,當進程發起IO 操作之後,就直接返回再也不理睬了,直到kernel發送一個信號,告訴進程說IO完成。在這整個過程中,進程完全沒有被block。

8. linux系統如何查看網路IO

首先 、用top命令查看

top - 16:15:05 up 6 days, 6:25, 2 users, load average: 1.45, 1.77, 2.14

Tasks: 147 total, 1 running, 146 sleeping, 0 stopped, 0 zombie

Cpu(s): 0.2% us, 0.2% sy, 0.0% ni, 86.9% id, 12.6% wa, 0.0% hi, 0.0% si

Mem: 4037872k total, 4003648k used, 34224k free, 5512k buffers

Swap: 7164948k total, 629192k used, 6535756k free, 3511184k cached

查看12.6% wa

IO等待所佔用的CPU時間的百分比,高過%時IO壓力高

其次、 用iostat -x 1 10

avg-cpu: %user %nice %sys %iowait %idle

0.00 0.00 0.25 33.46 66.29

Device: rrqm/s wrqm/s r/s w/s rsec/s wsec/s rkB/s wkB/s avgrq-sz avgqu-sz await svctm %util

sda 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

sdb 0.00 1122 17.00 9.00 192.00 9216.00 96.00 4608.00 123.79 137.23 1033.43 13.17 100.10

sdc 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00 0.00

查看%util 100.10 %idle 66.29

如果 %util 接近 100%,說明產生的I/O請求太多,I/O系統已經滿負荷,該磁碟可能存在瓶頸。

idle小於70% IO壓力就較大了,一般讀取速度有較多的wait.

同時可以結合vmstat 查看查看b參數(等待資源的進程數)

vmstat -1

如果你想對硬碟做一個IO負荷的壓力測試可以用如下命令

time dd if=/dev/zero bs=1M count=2048 of=direct_2G

此命令為在當前目錄下新建一個2G的文件

我們在新建文件夾的同時來測試IO的負荷情況。

閱讀全文

與linux系統io相關的資料

熱點內容
迷你編程登錄迷你號驗證碼是什麼 瀏覽:398
做數據表如何打出平方 瀏覽:447
在vmos下載的文件路徑在哪 瀏覽:771
有什麼購物app是用微信支付的 瀏覽:99
數控編程中夾持什麼意思 瀏覽:295
文件夾能容納多少張截圖 瀏覽:85
視頻文件查找 瀏覽:786
如何進入java的編程界面 瀏覽:371
二級開發者還有哪些app 瀏覽:241
app充值請聯系itunes 瀏覽:678
矢量app和cdr哪個好 瀏覽:85
系統文件壞了如何修復 瀏覽:20
鍵盤系統文件誤刪 瀏覽:738
白金英雄壇所有版本 瀏覽:842
ps文件轉hsj 瀏覽:382
哪個網站電影 瀏覽:490
ps4游戲文件格式名稱 瀏覽:290
caxa教程2007 瀏覽:832
新點是什麼小說網站 瀏覽:753
魔獸世界冰封王座3版本轉換器 瀏覽:418

友情鏈接