一文看懂Linux系統中塊設備/字符設備/裸設備的區別與聯繫

2019-08-07   波波說運維

概述

因為準備要對AIX系統上的資料庫擴容,然後發現/dev目錄下的hdisk 和 rhdisk磁碟,這兩個還是很容易混淆的,所以就順便整理一下塊設備、字符設備、裸設備方面的內容。


1、塊設備/字符設備/裸設備

1.1、塊設備

系統中能夠隨機(不需要順序)訪問固定大小數據片的設備稱作塊設備,這些數據片稱作塊。最常見的塊設備是硬碟。除此以外,還有軟盤驅動器、CD-ROM驅動器和快閃記憶體等等許多其他塊設備。

注意,他們都是以安裝文件系統的方式使用的,這也是塊設備的訪問方式。一般訪問單位為512k的整數倍。

1.2、字符設備

字符設備按照字符流的方式被有序訪問,像串口和鍵盤都屬於字符設備。如果一個硬體設備以字符流的方式被訪問,那就應該將它歸為字符設備。如果一個設備是隨機(無序的)訪問的,那麼它就屬於塊設備。訪問單位為位元組。

塊設備通過系統緩存進行讀取,不是直接和物理磁碟讀取。

字符設備可以直接物理磁碟讀取。不經過系統緩存。

1.3、裸設備

也叫裸分區(原始分區),是一種沒有經過格式化,不被unix通過文件系統來讀取的特殊字符設備。由應用程式負責對它進行讀取操作。不經過文件系統的緩存。

裸設備不使用buffer cache

1.4、使用裸設備的好處

因為使用裸設備避免了再經過unix作業系統這一層,數據直接從Disk到oracle進行傳輸,所以使用裸設備對於讀寫頻繁的資料庫應用來說,可以極大提高資料庫系統的性能。當然這是以磁碟的IO非常大,磁碟IO已經稱為系統瓶頸的情況下才成立。


2、是否隨機存取

這裡我們看下AIX系統的/dev目錄下的磁碟,可以看到有hdisk和rhdisk的磁碟

簡單的解釋:hdisk是塊設備,而rhdisk是字符設備。

塊設備和字符設備這兩種類型的設備的根本區別在於它們是否可以被隨機訪問——換句話說就是,能否在訪問設備時隨意地從一個位置跳轉到另一個位置。舉個例子,鍵盤這種設備提供的就是一個數據流,當你敲入「fox」 這個字符串時,鍵盤驅動程序會按照和輸入完全相同的順序返回這個由三個字符組成的數據流。如果讓鍵盤驅動程序打亂順序來讀字符串,或讀取其他字符,都是沒有意義的。所以鍵盤就是一種典型的字符設備,它提供的就是用戶從鍵盤輸入的字符流。對鍵盤進行讀操作會得到一個字符流,首先是「f」,然後是「o」,最後是「x」,最終是文件的結束(EOF)。當沒人敲鍵盤時,字符流就是空的。硬碟設備的情況就不大一樣了。硬碟設備的驅動可能要求讀取磁碟上任意塊的內容,然後又轉去讀取別的塊的內容,而被讀取的塊在磁碟上位置不一定要連續,所以說硬碟可以被隨機訪問,而不是以流的方式被訪問,顯然它是一個塊設備。

內核管理塊設備要比管理字符設備細緻得多,需要考慮的問題和完成的工作相比字符設備來說要複雜許多。這是因為字符設備僅僅需要控制一個位置—當前位置—而塊設備訪問的位置必須能夠在介質的不同區間前後移動。所以事實上內核不必提供一個專門的子系統來管理字符設備,但是對塊設備的管理卻必須要有一個專門的提供服務的子系統。不僅僅是因為塊設備的複雜性遠遠高於字符設備,更重要的原因是塊設備對執行性能的要求很高;對硬碟每多一分利用都會對整個系統的性能帶來提升,其效果要遠遠比鍵盤吞吐速度成倍的提高大得多。另外,我們將會看到,塊設備的複雜性會為這種優化留下很大的施展空間。

簡單來講,塊設備可以隨機存取,而字符設備不能隨機存取,那裸設備又該如何解釋呢?

難道裸設備,如磁碟裸設備也不能隨機讀取嗎?那在資料庫中用裸設備建一個2g的數據文件,為了存取最後一個數據塊,難道Oracle還要把前面的所有數據塊都讀一遍,顯然不符合事實,如果這樣解釋呢,作業系統不能隨機讀取,並不意味著資料庫也不能隨機讀取。


3、是否通過系統緩存

塊設備通過系統緩存進行讀取,不是直接和物理磁碟讀取。字符設備可以直接物理磁碟讀取。不經過系統緩存。(如鍵盤,直接相應中斷)

ASM必須使用字符設備作為ASM磁碟,而不能使用塊設備(如果使用塊設備,則必須使用ASMLib的支持)

通常意義上我們認為塊設備是可以隨機讀取的,但字符設備不能隨機讀取。那難道oracle在使用裸設備的時候必須對裸設備整個順序讀取一次,這絕對不可能。

"ASMLib是ASM的可選附件,它的目標是為ASM支持的內核提供發現和訪問塊設備的備選接口"。在大多數Unix系統上,字符設備顯示為/dev/rdsk,而在Linux上則顯示為/dev/raw/raw,唯一的例外情況是在ASM使用NAS文件系統文件作為磁碟時。


4、同一個設備兩種存儲方式的抽象

字符設備和塊設備是對同一個物理設備的兩種不同的存儲方式的抽象。

字符設備支持不定長的數據傳輸 (data transfers of arbitrary sizes),最小一個位元組,LVM和存儲設備的單次最大I/O只受 LTG (logical track group) 大小的限制,預設為128KB,可修改。

塊設備只能做定長的數據傳輸,數據必須經過 'kernel buffer cache'。

對 於 LVM 來講,這個限制是由於 LVM 在底層統一採用了 Block I/O 的讀寫方式。換句話說,不管你是通過字符設備還是塊設備訪問 LVM,最終都會以 Block I/O 的方式傳遞數據,而這種方式的確要求I/O到達LVM 時它的大小為 block size (512位元組) 的整數倍。

但通過字符設備和塊設備訪問 LVM的本質區別在於:

1. 塊設備雖然表面上可以接受『不定長』的『邏輯』請求(例如 dd bs=1),但它必須經過塊緩存(block buffer)模塊才能達到LVM I/O 模塊,而塊緩存I/O必然是以「一個」 512位元組塊進行的(不能大,也不能小)。所以,在LVM這一層發生的還是512位元組的讀寫。當你寫1位元組的時候,塊緩存模塊必須先把當前的512位元組從 LV里讀出來,更新一個位元組以後再把整個512位元組寫回去。如果你讀寫1KB,塊緩存必須把它分成兩個512位元組的請求發個LVM。所以在LVM層實際發 生了兩個512位元組的讀寫。

2. 字符設備從定義上支持不定長存取。但由於 LVM 底層實現採用了block I/O 的方式,I/O 必須以 512位元組 的整數倍進行,並且單個I/O 大小不能大於 LTG (預設128KB)。由於不經過緩存模塊的『打包』,1位元組的請求不能在到達LVM底層時變成512位元組,所以LVM返回 EINVAL 的錯。但4KB, 8KB 直到 128KB 的請求都會直接處理,不會被分拆成 512位元組,這是和塊設備的存取方式的本質區別。

這和ORACLE使用裸設備做數據文件沒有本質區別, ORACLE是可以對 裸設備/字符設備做隨機存取的。


後面會分享更多devops和DBA方面的內容,感興趣的朋友可以關注一下~