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.178linux.com/2886

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

相关推荐

  • 第十七周 作业–结合图形描述lvs原理

        LVS是Linux Virtual Server的简写,意即Linux虚拟服务器,是一个虚拟的服务器集群系统。本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一。   Lvs有三种模式分别是lvs-nat、lvs-dr、lvs-tun。下面分别介绍lvs-nat、lvs-dr…

    Linux干货 2016-12-07
  • 网络管理之网络配置

    一:博客 1 centos6网卡别名 在Linux系统中,我们可以在一块物理网卡上配置多个IP地址,以此来实现类似子接口的功能,我们称之为网卡别名。 设置网卡别名,先在/etc/sysconfig/network-scripts目录下将eth0文件复制名为eth0:1的文件,复制文件中的1可随意设置,但为方便管理建议按顺序排列 注意要修改ifcfg-eth0…

    Linux干货 2016-09-05
  • VSFTPD+PAM+[基于文件虚拟用户认证 | 基于MYSQL虚拟用户认证]

    VSFTPD+PAM+[基于文件虚拟用户认证 | 基于MYSQL虚拟用户认证] VSFTPD+PAM+[基于文件虚拟用户认证 | 基于MYSQL虚拟用户认证] 一、实验环境 二、实验步骤 1、通过mysql数据库方式虚拟用户认证 1.1数据库配置 1.2FTP配置 1.3测试 2、通过文件方式进行虚拟用户认证 一、实验环境 CentOS 6.7+vsftpd…

    Linux干货 2016-04-18
  • Linux之任务计划 crontab

    Linux之任务计划    用过windows的同学应该都知道在控制面板中有一个“任务计划”选项,我们可以通过向导设置让计算机在某个时间点或者开机时运行某个脚本或者批处理等等,方便我们的日常管理监视工作;同样在Linux系统中,如果我们想在开机时就运行某个操作,可以直接将命令写入/etc/rc.local中,该操作就会在机器开机时运行;如…

    Linux干货 2015-05-18
  • Linux启动流程

    Linux的启动流程有以下部分组成,以下流程以CentOs 6.8为例 1、POST加电自检,检测各项硬件工作是否正常,BIOS选择启动设备。 2、根据设备的前446字节,加载bootloader程序 3、initramfs是1.5阶段,intramfs文件是创建系统时生成的文件。intramfs是一个过渡阶段,initramfs加载系统的一些设备驱动,比如…

    2017-05-15
  • 第一天,学习

    好好学习,天天向上

    Linux干货 2016-08-08