Linux 環境 SSD(固態硬盤)使用指南

原文鏈接:http://www.jinbuguo.com/storage/ssd_usage.html

前言

因為SSD有著諸多與傳統機械式硬盤不同的特點,而且這些特點導致了SSD在實際使用中的性能和壽命與其使用方法緊密相關。所以并不是說買來一塊非
常牛X的SSD就萬事大吉了。另一方面,SSD的性能并不像機械式硬盤那樣比較穩定(浮動范圍小),而是呈現出一種離散的特點(浮動范圍大),最佳狀態與
最差狀態相差甚遠(上百倍),所以如何避免最差狀態比如何發揮最佳狀態更重要。

分區對齊

如果要對一塊SSD進行分區,然后再使用,就會遇到這個問題。當然,也可以不對它進行分區以避免這個問題。對于Linux來說,不分區直接使用就是
直接格式化 /dev/sdx 設備(比如:mkfs.xfs /dev/sdx),然后再 mount /dev/sdx /mnt/point

考慮到使用習慣、預留空間(見下文)的問題,以及安裝引導程序(如:grub)的要求,不做分區直接使用并不是個好主意。幸運的是,分區對齊問題是可以得到完美解決的。

害處

如果SSD上的分區分割點處于未對齊SSD block
size倍數的狀態,SSD效能就不能完全發揮,系統可能會有卡頓的感覺,另外,未對齊的分割點還會造成SSD在連續寫入小文件時,增加無謂的SSD額外
寫入/擦除動作從而大幅影響SSD的壽命,而這偏偏是SSD使用中最該避免的。

分區不對齊,對4KB隨機寫入的影響最大,實際測試表明,在其他因素相同的情況下,分區不對其導致的性能差距最大可達10倍。

CHS、LBA、block(塊)

在了解事情的來龍去脈之前,先得把傳統硬盤的幾個概念拿出來復習一下。

CHS(Cylinder-head-sector)是最早用于訪問硬盤的尋址方式。雖然CHS的值現在早已不再與實際的物理值相對應(只是個邏輯值),但是依然有許多磁盤管理程序(比如fdisk/cfdisk)使用CHS的方式來理解硬盤。

Linux 環境 SSD(固態硬盤)使用指南

side/head

硬盤一般是由一片或幾片圓形薄膜疊加而成。每個圓形薄膜都有兩個"面"(Side),這兩個面都是用來存儲數據的。盤面由上而下從"0"開始編號,
依次稱為0面、1面、2面……由于每個面都專有一個讀寫磁頭,也常用0頭(head)、1頭……稱之。硬盤面數(或頭數),少的只有2面,多的可達數十
面。

按照CHS規范,head使用8bit編址,因此最多可以有256個磁頭(0-255)。但是由于某些古董程序只能最大支持到255個磁頭,出于兼容性考慮,絕大多數場合的默認值依然是255個磁頭。

track

讀寫硬盤時,磁頭不動,磁盤是旋轉的,則連續寫入的數據是排列在一個圓周上的。我們稱這樣的圓周為一個磁道(Track)。

磁頭不動,就是在一個磁道上讀寫;磁頭移動,就會在不同磁道上讀寫。

按照CHS尋址規范,由外向內從"0"開始順序編號。不過其編址時使用的位寬并不是一個定值(取決于不同的規范),我們姑且可以認為其足夠大。

cylinder

各面上磁道號相同的磁道合起來,稱為一個柱面(cylinder)。也就是距軸的距離相同的一組track所形成的圓筒。

按照CHS尋址規范,cylinder和track一樣,也由外向內從"0"開始順序編號。并且其編址位寬足夠大。

cylinder也是磁盤分區時的最小單位,分區是按磁道和柱面連續分布的(即每個分區,都是粗細連續的一組筒子)。

下面是一個fdisk的輸出,主意最后一行:

# fdisk /dev/sda
Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4): 1
First cylinder (1-524, default 1):

Sector

一個track上可以容納"較多"的數據,而主機讀寫時往往并不需要一次讀寫那么多,于是,磁道又被按512或4096字節劃分成若干段,每段稱為一個扇區(Sector)。一個扇區的大小是固定的512或4096字節。

計算機對硬盤的讀寫,是以扇區為最小單位。即使只讀某一個字節,也必須一次把這個字節所在的扇區中的512或4096字節全部讀入內存。

按照CHS尋址規范,Sector的編號始終是從"1"開始的(不是"0")。由于使用6bit編址,所以其最大值是63,也就是說既不存在 sector 0 也不存在 sector 64 。目前所有機械式硬盤在邏輯CHS模式中都使用63這個最大值。

block

Block是文件系統的最小存取空間。一個 Block
最多僅能容納一個文件(即不存在多個文件同一個block的情況)。如果一個文件比block小,他也會占用一個block,因而block中空余的空間
會浪費掉。而一個大文件,可以占多個甚至數十個成百上千萬的block。

# df
/                  (/dev/dsk/c0t3d0s0 ):  573548 blocks   226057 files
/proc              (/proc             ):       0 blocks     3854 files
/var               (/dev/dsk/c0t3d0s1 ): 1897206 blocks   250028 files
/var/run           (swap              ):  611424 blocks    26300 files
/tmp               (swap              ):  611424 blocks    26300 files

sector 和block的差別

  1. sector 是硬盤存取的最小單位,是512B或4096B

  2. block 是文件系統的最小存取單位,可以隨意設定,但必須是sector的整數倍。如ext2 fs的block缺省是4k

應該根據自己系統應用的特點,合理規劃block size:若block太大,則存取小文件時,有空間浪費的問題;若block太小,則硬盤的
Block 數目會大增,而造成 inode 在指向 block 時候的一些搜尋時間的增加,又會造成大文件讀寫方面的效率較差。

磁盤容量

先看一個500G的硬盤在 fdisk -l 時顯示的信息:

# fdisk -l /dev/sda

Disk /dev/sda: 500.1 GB, 500107862016 bytes
255 heads, 63 sectors/track, 60801 cylinders, total 976773168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1              63     8000369     4000153+  83  Linux
/dev/sda2         8000370    95891984    43945807+  83  Linux
/dev/sda3        95891985   427923404   166015710   83  Linux
/dev/sda4       427923405   976768064   274422330   83  Linux

可以看出,磁盤總容量=磁頭數*每磁道扇區數*柱面數*扇區大小。當然,這里的磁頭數、扇區數、柱面數并不是物理真實值,而是邏輯值。甚至對于4KB扇區的硬盤,扇區大小也可能是邏輯值。

LBA尋址機制

上面說的CHS尋址方式其實在實踐中早就被丟進垃圾箱了。目前在實踐中真正使用的是48位LBA(Logical Block
Address)尋址方式。LBA是非常單純的一種尋址模式:從0開始編號來定位區塊(扇區),第一區塊LBA=0,第二區塊LBA=1,依此類推。以每
扇區512字節計算,容量上限可達128PB。LBA尋址模式完全屏蔽了硬盤的物理結構,而將其簡單的抽象成一維條帶,非常便于操作系統的理解。

原因分析

了解了上面的知識之后,現在知道了機械硬盤從很早前開始,扇區大小就被定義為512字節,而最新的"先進格式"機械盤終于把物理扇區提高到
4KB(4096字節)。機械式硬盤的最小操作單位是扇區,也就是說,無論讀取還是寫入1個字節、10個字節、500字節,實際的操作都是512字節。當
然,對于4KB扇區的機械式硬盤來說,所有讀寫操作都會被向上取整到4KB的整數倍。

但SSD的操作方式與此不同。SSD不像HDD那樣只有讀/寫兩種操作而且還是統一的,SSD有三種操作:讀/寫/擦除。閃存的讀寫單位是4KB或8KB大小的,而且閃存的擦除(又叫編程)操作是按照128或256頁大小的來操作的。

傳統上,LBA模式的HDD第一個分區的起始點從63邏輯扇區(63x512B=31.5KB)開始,對于扇區大小為512B的HDD來說,這當然
沒什么問題。但對于SSD和新式HDD來說,就會造成用戶的第一個數據的前4KB會存放在系統"邏輯扇區"的31.5KB~35.5KB間,這樣持續下去
會造成后面所有的數據都會卡在2個物理扇區(頁)容量之間,我們知道扇區(頁)為磁盤寫入的最小單位,如果卡在2個扇區(頁)之間,寫入的時候就需要進行
讀-改寫操作(對SSD來說讀-擦-寫),造成性能的下降。

Linux 環境 SSD(固態硬盤)使用指南

分割點應該放在哪里呢?

簡單的說,應該放在SSD最大操作單位"塊",也就是block size整數倍的位置。

對于單通道的閃存設備,這很簡單,也很好理解。但事實上,幾乎所有的SSD都不是單通道的,這時候應該空出多少呢?

多通道的閃存設備也是把數據拆成一個一個的塊,然后分別對每個通道進行讀寫操作,這個塊的大小和所使用的閃存芯片的塊的大小是一樣的。如果多通道
SSD會把數據再進一步拆分然后才寫到各個通道的話,情況就會變得復雜了。不過目前的SSD主控似乎還沒有這么聰明,目前多通道寫入時最小的數據單位依然
是閃存塊的大小。因此,在目前的情況下,我們完全可以不考慮設備是幾通道的,直接把分區分割點設在block
size整數倍的位置即可。也許未來需要把分割點設置在"通道數*block-size"整數倍的位置?

FDISK

在給出最終解決方案之前,先來了解一下fdisk工具:

# fdisk -h
Usage:
 fdisk [options] <disk>    change partition table
 fdisk [options] -l <disk> list partition table(s)
 fdisk -s <partition>      give partition size(s) in blocks

Options:
 -b <size>             sector size (512, 1024, 2048 or 4096)
 -c[=<mode>]           compatible mode: 'dos' or 'nondos' (default)
 -h                    print this help text
 -u[=<unit>]           display units: 'cylinders' or 'sectors' (default)
 -v                    print program version
 -C <number>           specify the number of cylinders
 -H <number>           specify the number of heads
 -S <number>           specify the number of sectors per track

我們通常并不使用任何選項,但是為了強制分割點的位置對齊,就必須強制指定如下三個參數:

  1. -b

  2. 指定扇區的大小,只能取 512/1024/2048/4096 之一。
    注意,經過本人實測,使用大于512的其他值(假定是N),會導致fdisk只能使用到真實容量的512/N。所以最好不要使用該選項。

  3. -H

  4. 指定磁頭數,只能取 1-256 之間的整數。

  5. -S

  6. 指定每磁道扇區數,只能取 1-63 之間的整數。

這三個參數值的乘積就是一個邏輯柱面的總大小,也就是最小分割單位了。

解決方案

經過前面的講解,現在知道,只要把"塊"作為SSD的最小單位來劃分磁盤就能完美解決分區對齊的問題。

現在假定我們拿到一塊SSD的參數是這樣的:每個頁的大小是8KB、每256個頁組成一個塊,那么也就是說我們必須以
256*8KB=2097152B=2048KB=2MB為最小單位對其進行分區。也就是說,我們可以通過強制指定fdisk的命令行參數,使每個柱面
(cylinder)的大小為2MB即可達到目的(假定每扇區512字節):

fdisk -u=cylinders  -H 128 -S 32  /dev/sdx

如果覺得每個柱面(cylinder)的大小為2MB還是不夠大,那么可以加大到4MB(假定每扇區512字節):

fdisk -u=cylinders  -H 256 -S 32  /dev/sdx

此外,還需要注意一個細節,那就是第一個分區的起點不能從默認的第一個柱面開始,而是要從第2個柱面開始,否則第一個分區有可能依然不會對齊。如下圖所示:

Command (m for help): n
Command action
   e   extended
   p   primary partition (1-4)
p
Partition number (1-4, default 1):
Using default value 1
First cylinder (1-800, default 1): 2Last cylinder, +cylinders or +size{K,M,G} (2-800, default 800): 500

注意 First cylinder 那一行,那里的默認值是1,但是不能用它,要手動修改為2。

導致這個問題的原因,據Google說是fdisk會對從 cylinder 1 開始的扇區特殊對待,自作主張的向前平移分區起點。不過,既然新版本的fdisk已經修正了這個bug,我們就不必再去考古了。

對齊檢查

如何檢查分區是否確實已經對齊呢?方法是使用"fdisk -u=sectors -l /dev/sdx"查看。例如:

# fdisk -u=sectors -l /dev/sda

Disk /dev/sda: 671 MB, 671088640 bytes
128 heads, 32 sectors/track, 320 cylinders, total 1310720 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x7bf5a16d

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1              63       40959       20448+  83  Linux
/dev/sda2           40960       79871       19456   83  Linux
/dev/sda3           81920      163839       40960   83  Linux

首先看 Sector size 的大小,有logical/physical兩個值,都是512字節。

sda1分區的Start=63,那么就表示sda1分區的起始扇區頭距離LBA0的距離是63*512B=31.5KB,顯然是未對齊的。

sda2分區的Start=40960,表示sda2分區的起始扇區頭距離LBA0的距離是40960*512B=20MB=5*2*2MB,顯然
既在2MB大小的塊邊緣對齊,也在4MB大小的塊邊緣對齊;再看sda2分區的End=79871,表示sda2分區的終止扇區尾距離LBA0的距離是
(79871+1)*512B=39MB,顯然只能在1MB大小的塊邊緣對齊,但是不能在2MB/4MB塊的邊緣對齊。

sda3分區的Start=81920,表示sda3分區的起始扇區頭距離LBA0的距離是81920*512B=40MB=5*4*2MB,顯然
既在2MB大小的塊邊緣對齊,也在4MB大小的塊邊緣對齊,甚至對于8MB大小的塊也是對齊的;再看sda3分區的End=163839,表示sda3分
區的終止扇區尾距離LBA0的距離是(163839+1)*512B=80MB=5*2*2*2*2MB,顯然可以在2MB/4MB/8MB/16MB塊
的邊緣對齊。

可見sda3是對齊最完美的分區,而sda1則是最糟糕的。

文件系統

現在SSD已經被完美的分區了,接下來就是創建文件系統了,那么哪個文件系統才是最適合SSD的呢?因為Linux系統有如此多的文件系
統:etx2/ext3/ext4/reiser3/reiser4/JFS/XFS/Btrfs/NILFS2……在HDD的時代,選擇合適的文件系統
就一直是個令人頭痛的問題。直到目前為止,不得不說,沒有任何一個文件系統和SSD是絕配。

未完待續。。。

原創文章,作者:追馬,如若轉載,請注明出處:http://www.www58058.com/2886

(0)
追馬追馬
上一篇 2015-04-08
下一篇 2015-04-09

相關推薦

  • Centos Linux基礎入門知識類

    Centos Linux基礎入門知識類 ?1.1Linux終端介紹 ?1.2基本命令的使用:ls、pwd、cd。 ?1.3 查看系統和BIOS硬件時間。 ?1.4 Linux如何獲得幫助,Linux關機命令:shutdow、init等。 ?1.5 YUM本地源配置與開機自動掛載光盤 前言: 很多學習Linux的同學或多…

    Linux干貨 2017-03-26
  • 馬哥第一天

    來這兒的第一天

    2018-03-26
  • 8.1_Linux習題和作業

    7.28 作業 1、將/etc/issue文件中的內容轉換為大寫后保存至/tmp/issue.out文件中 1 # cat /etc/issue | tr 'a-z' 'A-Z'whoi > /tmp/issue.out 2、將當前系…

    Linux干貨 2016-08-04
  • 磁盤管理

    磁盤管理磁盤管理 本章內容 ?磁盤結構 ?分區類型 ?管理分區 ?管理文件系統 ?掛載設備 ?管理虛擬內存 設備文件 ?I/O Ports: I/O設備地址 ?一切皆文件: open(), read(), write(), close() ?設備類型: 塊設備:block,存取單位“塊”,磁盤 字符設備:char,存取單位“字符”,鍵盤 ?設備文件:關聯至一…

    Linux干貨 2016-08-26
  • M25 Linux 學習,FHS標準

    FHS FHS(英文:Filesystem Hierarchy Standard 中文:文件系統層次結構標準),多數Linux版本采用這種文件組織形式,FHS定義了系統中每個區域的用途、所需要的最小構成的文件和目錄同時還給出了例外處理與矛盾處理。 FHS定義了兩層規范,第一層是, / 下面的各個目錄應該要放什么文件數據,例如/etc應該要放置設置文件,/bi…

    2017-07-15
  • 開班第一天,新獲得的技能

    新接觸命令 lscpu 顯示CPU信息 gedit 文件名 類似于記事本 ** 注意 這個命令適用于圖形界面。 cat /proc/partition 顯示分區信息 cat /proc/meminfo 顯示內存大小 cat /proc/swaps 顯示虛擬內存 cat …

    Linux干貨 2017-02-17
欧美性久久久久