下面的命令操作以及示例主要是针对Ubuntu系统

CPU常见概念与查询

时钟速度

  • CPU时钟速度越高,CPU 运行速度越快
  • 时钟速度则测量 CPU 每秒执行的周期数,以 GHz(千兆赫)为单位
  • 周期是由内部振荡器同步的脉冲,举例,时钟速度为 3.2 GHzCPU 每秒执行 32 亿个周期
  • CPU规格中会列出最大睿频和处理器基本频率,处理器基本频率是指 CPU 的正常运行速度,而最大睿频是指处理器采用睿频加速技术后可以达到的最高速度

下图来源于Intel时钟速度说明image.png

超线程技术

  • CPU架构当中包含两个最主要的模块

    • Processing Unit(运算处理单元,PU),负责实际的运算,如加减乘除,是实际干活的
    • Architectual State(架构状态单元,AS),执行逻辑和调度方面操作,分配运算任务给PU
  • 超线程技术Hyper-threading,是硬件架构层的多线程,通过调整AS模拟出来一个逻辑核,最终实现一个物理核里面有两个AS,一个PU

开启超线程技术的优缺点

优点

  • CPU利用率增高:使用更多资源去执行调度,接收任务,提高PU的使用效率
  • 并行能力增强:处理多进程/线程的能力加强,对于支持多线程的程序比较明显

缺点

  • 单核性能下降: 对于单线程程序来说,两个AS的开销大于一个AS的(程序在选择AS上面存在开销)

开启超线程技术后,单个物理核的时钟周期还是一样的,所以对于整个CPU的运算能力的计算方式还是

整个CPU运算能力 = 物理核心数量 * 每个核心最大睿频频率
或者
              = 物理核心1的最大睿频频率 + 物理核心2的最大睿频频率 + ....

目前CPU的发展主要朝着多核方向,主频和最大睿频提升幅度不大,但是核心越来越多,目前最新的12代core i7,i9的还有性能核(超线程,最大睿频频率较高)和能效核(单线程)这种架构

CPU信息查询

使用lscpu命令查询结果如下

$ lscpu
//  --snip--
CPU:                     12
  在线 CPU 列表:        0-11
厂商 ID:                GenuineIntel
  型号名称:             Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz
    CPU 系列:           6
    型号:               158
    每个核的线程数:     2
    每个座的核数:       6
    座:                 1
    步进:               10
    CPU 最大 MHz:       4500.0000
    CPU 最小 MHz:       800.0000
// --snip--

从结果输出知道CPU的型号是Intel(R) Core(TM) i7-9750H CPU @ 2.60GHz,可以知道是属于Core系列i79代的针对移动设备进行优化的CPU,基础频率是2.6GHz,产品型号每个参数所表示的意思可以参考Intel处理器编号和名称

CPU是6核12线设计,最大频率是4.5GHz,最低频率是0.8GHz

也可以通过cat /proc/cpuinfo具体每个系统所识别到的CPU信息,一般系统会识别到AS(逻辑核)的数量作为CPU的总数

服务器一般会使用Xeon系列的处理器,具体处理计算性能和Core一样

内存相关

内存信息查询

一般使用内存的时候主要关心内存大小,内存频率就不考虑了

$ free -hw
               total        used        free      shared     buffers       cache   available
内存:          31Gi        11Gi       5.4Gi       1.0Gi       867Mi        13Gi        18Gi
交换:          27Gi          0B        27Gi

第一行内存数据参数

  • total: 系统总的可以使用的物理内存大小,该值是used + free + buff/cache的总和
  • used: 系统已经被使用的物理内存大小
  • free: 系统还有多少内存可以被使用,系统还未分配出去的内存,真正尚未被使用的物理内存数量
  • shared: 被多个进程共享使用的内存的大小
  • buffers:

    • buff所使用的物理内存大小,表示linux内存中的Buffer cache,缓冲区缓存,主要提高写磁盘的效率
    • 设计用来在系统对块设备进行读写的时候,对块进行数据缓存的系统来使用
    • 块设备是一种具有一定结构的随机存取设备,对这种设备的读写是按块进行的,使用缓冲区来存放暂时的数据,待条件成熟后,从缓存一次性写入设备或者从设备一次性读到缓冲区
    • 在写磁盘的时候,数据会先写入buffer,后台会有一个sync(该命令可以手动执行)程序周期性的去把buffer中的数据刷新到磁盘,并且释放对应的buffer
  • cache:

    • cache所使用的物理内存大小,表示linux内存中的Page cache,页面缓存,主要提高读磁盘的效率
    • 用来作为文件系统上的文件数据的缓存来用,当进程对文件进行读写的时候把文件映射到内存当中进行操作
    • 对于bufferscache的解释有很多,需要自行去学习
  • available

    • 可以被应用程序所使用的物理内存大小,应用程序认为可用内存数量
    • 对于内核来说,buff/cache所占用的资源都是已经被分配出去的,对于应用程序来说,申请内存的时候如果空闲内存不够,内核会回收buff/cache的内存
    • 该参数的计算方式是free + buff/cache或者total - used,实际该值的结果会比计算出来的小一点

第二行交换空间数据参数和第一行的一致,但是这部分空间是磁盘上的

cache内存的释放

  • 在内存够用的时候cache内存的使用会加快进程对文件的读写速度,所以在内存压力较大的情况下,有必要清空释放 cache
  • 内核会在内存将要耗尽的时候,触发buffer/cache内存回收的工作,以便释放出内存给急需内存的进程使用
  • 内核会对比 cache 中的数据和对应硬盘文件上的数据是否一致,如果不一致需要写回,之后才能回收,在释放cache内存的时候,系统磁盘 IO 会大幅度升高

手动回收内存

# 先把buffer当中的数据同步到磁盘上面
$ sync

# 触发回收内存操作,参数3表示清除pagecache和slab分配器中的缓存对象
$ echo 3 > /proc/sys/vm/drop_caches 

上述操作执行完成之后再次执行内存查看命令,可以发现有将近10G的内存释放

$ free -wh                         
               total        used        free      shared     buffers       cache   available
内存:          31Gi        10Gi        16Gi       1.0Gi        14Mi       3.8Gi        18Gi
交换:          27Gi          0B        27Gi

系统基本信息获取

使用工具inxi项目地址

安装

$ sudo apt install inxi

获取信息,-F参数指定获取所有检测信息

$ inxi -F
System:    Host: gong Kernel: 4.15.0-112-generic x86_64 bits: 64 Console: tty 0 Distro: Ubuntu 18.04.6 LTS
Machine:   Device: desktop Mobo: N/A model: NSB5171C v: G769-032 serial: N/A
           UEFI: American Megatrends v: 5.12 (G769-032) date: 05/11/2020
CPU:       Quad core Intel Core i5-6500 (-MCP-) cache: 6144 KB
           clock speeds: max: 3200 MHz 1: 3200 MHz 2: 3200 MHz 3: 3200 MHz 4: 3200 MHz
Graphics:  Card: Intel HD Graphics 530
           Display Server: N/A driver: i915 tty size: 150x35 Advanced Data: N/A for root out of X
Network:   Card-1: Intel I210 Gigabit Network Connection driver: igb
           IF: enp5s0 state: up speed: 1000 Mbps duplex: full mac: cc:d3:9d:9f:d5:1d
           Card-2: Intel I210 Gigabit Network Connection driver: igb
           IF: enp6s0 state: down mac: cc:d3:9d:9f:d5:1e
           Card-3: Intel I210 Gigabit Network Connection driver: uio_pci_generic
           IF: N/A state: N/A speed: N/A duplex: N/A mac: N/A
           Card-4: Intel I210 Gigabit Network Connection driver: uio_pci_generic
           IF: N/A state: N/A speed: N/A duplex: N/A mac: N/A
           Card-5: Intel I210 Gigabit Network Connection driver: uio_pci_generic
           IF: N/A state: N/A speed: N/A duplex: N/A mac: N/A
           Card-6: Intel I210 Gigabit Network Connection driver: uio_pci_generic
           IF: N/A state: N/A speed: N/A duplex: N/A mac: N/A
Drives:    HDD Total Size: 2064.4GB (4.0% used)
           ID-1: /dev/sda model: ST2000NM0055 size: 2000.4GB
           ID-2: /dev/sdb model: TS64GSSD420K size: 64.0GB
Partition: ID-1: / size: 1.8T used: 69G (4%) fs: ext4 dev: /dev/sda4
           ID-2: /boot size: 2.0G used: 84M (5%) fs: ext4 dev: /dev/sda3
           ID-3: swap-1 size: 8.59GB used: 0.00GB (0%) fs: swap dev: /dev/sda2
RAID:      No RAID devices: /proc/mdstat, md_mod kernel module present
Sensors:   System Temperatures: cpu: 36.5C mobo: 29.8C
           Fan Speeds (in rpm): cpu: N/A
Info:      Processes: 281 Uptime: 69 days Memory: 5668.0/7894.5MB Init: systemd runlevel: 5
           Client: Shell (bash) inxi: 2.3.56 

系统状态监控

对于大部分web项目来说,很多性能瓶颈都是出现在数据库上面,数据库的瓶颈是在磁盘IO上面

下面会使用工具iotopiostat

iostat使用

该工具主要反映系统当前的CPU和磁盘的整体状态,方便快速定位系统瓶颈
项目地址
安装

$ sudo apt install sysstat

之后执行如下命令,-c表示只显示CPU状态信息,3表示每3s刷新一下结果

$ sudo iostat -c 3
Linux 5.15.0-56-generic (gong)     2022年12月05日     _x86_64_    (12 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           7.83    0.01    2.69    0.18    0.00   89.30

输出参数

  • % userCPU 处在用户模式下的时间百分比
  • % niceCPU处在带 NICE 值的用户模式下的时间百分比
  • % systemCPU 处在系统模式下的时间百分比
  • % iowait:等待输入输出完成时间的百分比,值很高,表示硬盘存在 磁盘I/O 瓶颈
  • % steal:管理程序维护另一个虚拟处理器时,虚拟 CPU 的无意识等待时间百分比
  • % idle:空闲时间百分比,值如果很高,表示 CPU 较空闲,同时也可能反映磁盘IO速度不行

执行如下命令,-d表示只显示磁盘状态

$ iostat -d 3
Linux 5.15.0-56-generic (gong)     2022年12月05日     _x86_64_    (12 CPU)

Device             tps    kB_read/s    kB_wrtn/s    kB_dscd/s    kB_read    kB_wrtn    kB_dscd
  • tps:该设备每秒的传输次数,一次传输是一次 I/O 请求,多个逻辑请求可能会被合并为一次 I/O 请求,一次传输请求的大小是未知的
  • kB_read/s:每秒从设备读取的数据量
  • kB_wrtn/s:每秒向设备写入的数据量
  • kB_read:读取的总数据量
  • kB_wrtn:写入的总数量数据量

iotop使用

项目地址
安装

$ sudo apt install iotop

执行命令

$ sudo iotop
Total DISK READ:         0.00 B/s | Total DISK WRITE:         0.00 B/s
Current DISK READ:       0.00 B/s | Current DISK WRITE:       0.00 B/s
    TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
      1 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  init splash
      2 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [kthreadd]
      3 be/0 root        0.00 B/s    0.00 B/s  ?unavailable?  [rcu_gp]
      4 be/0 root        0.00 B/s    0.00 B/s  ?unavailable?  [rcu_par_gp]
      5 be/0 root        0.00 B/s    0.00 B/s  ?unavailable?  [netns]
      7 be/0 root        0.00 B/s    0.00 B/s  ?unavailable?  [kworker/0:0H-events_highpri]
      9 be/0 root        0.00 B/s    0.00 B/s  ?unavailable?  [mm_percpu_wq]
     10 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [rcu_tasks_rude_]
     11 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [rcu_tasks_trace]
     12 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [ksoftirqd/0]
     13 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [rcu_sched]
     14 rt/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [migration/0]
     15 rt/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [idle_inject/0]
     17 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [cpuhp/0]
     18 be/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [cpuhp/1]
     19 rt/4 root        0.00 B/s    0.00 B/s  ?unavailable?  [idle_inject/1]

Total DISK READ Total DISK WRITE 表示进程和内核线程之间的,内核块设备子系统的总的读写速度

Current DISK READCurrent DISK WRITE表示实际磁盘 I/O 读写速度

可以使用左右按键调整排序,找到最大读写速度的进程,如果磁盘最大的随机读写速度是100MB/S,数据库某个查询请求占用了80MB/S的速度读取磁盘,那么其他请求就只剩下一点点磁盘速度了,这个是导致数据库查询经常时间差距非常大的一个原因

磁盘性能测试

使用工具fio项目地址

安装

$ sudo apt install fio

fio中参数解释

  • -filename=

    • 该参数不要使用,超级坑,网络上有很多教程都是说要指定这个参数,所以我们要知道这个参数,并且一定要避开这个雷
    • 如果刚好指定了参数是系统盘[根分区或者/boot分区]的话,请直接重装系统吧
    • 如果是数据盘的话,就可以准备格式化了
    • 本人已经付出惨痛的代价,请使用-directory参数,使得程序读写数据的时候限制在某个文件夹内
    • 这个出现问题是随机的,可能这一次执行的时候重启机器后没问题,可能下一次就出问题了
    • 这个参数使用的时候会指定测试磁盘名称,指定某个要测试的裸设备,切勿在系统分区做测试,会破坏系统分区,而导致系统崩溃,参数比如/dev/sda/dev/sdb2
    • 假设现在已经指定了/dev/sda参数,fio程序执行的时候直接从第一个扇区随机写入数据,但是每块硬盘分区的前面几个扇区是非常重要的,包含了该块硬盘的扩展引导程序,分区标志,该块分区的文件类型等重要的数据
  • -directory=: 指定测试文件夹的位置,可以先创建一个文件夹,比如/home/test-files,然后指定-directory=/home/test-files,这样fio的读写就会限制在固定位置了
  • -direct=: Linux在读写时,数据会先写到缓存,再在后台写到硬盘,读的时候也是优先从缓存中读,这样访问速度会加快,但是一旦掉电,缓存中数据就会清空,一种模式为DirectIO,可以跳过缓存,直接读写硬盘,为了绕开这个优化,使得测试结果更加真实,需要设置该参数为1
  • -ioengine=: io引擎选择,可选项有libaio(Linux本地异步I/O), rdb(通过librbd直接访问CEPH Rados ),推荐配置为libaio
  • -iodepth=: 配置发送命令队列深度,防止测试时候占用太多内存导致系统崩溃,推荐配置为16
  • -bs=: 配置单次io块的大小,测试的时候需要把该参数多次配置为4k, 16k, 256k等参数,用于测试在不同文件大小下面的读写速度
  • -numjobs=: 测试使用的线程数量,依据机器性能配置,推荐配置为与机器物理核心相同的数量
  • -size=: 配置每个线程读写的数量大小,推荐配置为1G以上,5G左右比较合适
  • -runtime=: 配置测试时间,单位是秒,如果不配置该项,size配置的值全部读完或者写完之后程序才会退出
  • -rw=: 读写模式配置,可选项randread(随机读), randwrite(随机写),randrw(随机混合读写),read(顺序读),write(顺序写),rw(顺序读写)
  • -rwmixwrite=: 混合读写模式下面的写的占比,可选值0-100,比如配置为30,那么写占据30,读占据70,该参数和rwmixread相对,只配置一个就行
  • -thread-fork:两个参数无配置值,声明即可,-thread表示使用创建线程测试,推荐采用该参数
  • -group_reporting: 表示汇总每个测试的信息,该参数只声明即可
  • -name: 定义测试任务名称
  • -lockmem=:定义测试使用的最大内存,可以配置为1g

安装与获取文档

需要依赖gcc

$ sudo apt install gcc

从源码构建与安装

$ git clone https://github.com/axboe/fio.git
$ cd fio
$ ./configure
$ make
$ sudo make install

创建文档,需要依赖sphinx

$ sudo apt install python3-sphinx
$ make -C doc html

之后在浏览器中访问对应的首页即可,访问地址如下,效果如下

file://${此处替换为项目的绝对路径}/doc/output/html/index.html

使用

检测前需要使用iotop命令查看是否有其他进程占用较大的磁盘速度,如果有需要把那些程序关闭,以免影响测试结果,执行测试命令需要root

本次测试采用的是一块固态硬盘

测试磁盘/dev/sda (可以通过fdisk -l命令查看),测试使用文件夹位置是/home/test-file的性能,随机读,总测试文件大小为5G,测试块文件大小为4k,使用双线程测试

$ fio -directory=/home/test-file -direct=1 -ioengine=libaio \
-bs=4k -size=5G -numjobs=2 -iodepth=16 -thread -rw=randread \
-group_reporting -name="5G_4KB_randread_test" -lockmem=1G
# 由于输出比较多,所以下面逐行分析输出


# rw参数表示运行模式是随机读,测试块文件大小是4k,该行主要是对输入命令的关键信息等打印
5G_4KB_randread_test: (g=0): rw=randread, bs=(R) 4096B-4096B, 
(W) 4096B-4096B, (T) 4096B-4096B, ioengine=libaio, iodepth=16
...
# fio版本为3.28,尽量使用最新版本,以免下面输出参数缺少
fio-3.28
Starting 2 threads
# 开启两个线程,每个线程会使用-size配置的数据
5G_4KB_randread_test: Laying out IO file (1 file / 5120MiB)
5G_4KB_randread_test: Laying out IO file (1 file / 5120MiB)
# 开启线程的多少和顺序读写,随机读写无关系,对用户而言,线程参数只表示重复执行测试任务几次
# [100%]表示测试100%完成
# r=143MiB/s表示读的次数是143MiB,如果是测试写的话,该参数会是w=???MiB/s
# r=36.6k IOPS,全称Input/Output Operations Per Second,表示每秒的读次数
# 意味着每秒有36.6K次的读操作完成
# 该次执行的测试块大小是4K,所以也可以使用计算方式如下:随机读速度 = 测试块大小 * IOPS大小
Jobs: 2 (f=2): [f(2)][100.0%][r=143MiB/s][r=36.6k IOPS][eta 00m:00s]

# 上面的数据已经足够知道磁盘读写性能了,下面的数据是扩展,了解即可
# 下面参数当中通用的字段含义: 
# min-最小,max-最大,avg-平均,stdev-标准差,samples-样本数
# usec表示时间单位/微秒,msec表示时间单位/毫秒
5G_4KB_randread_test: (groupid=0, jobs=2): err= 0: pid=1304003: Fri Dec  9 14:46:54 2022
  # 表示对读性能的分组标识,如果是测试写性能,则该参数是write
  # 由于我们采用两个线程进行任务,同时配置了测试文件总大小为5G,
  # 所以总的读的磁盘文件是10G,每个线程都读了5G的磁盘
  # 读取10G磁盘总共耗时71.486秒
  read: IOPS=36.7k, BW=143MiB/s (150MB/s)(10.0GiB/71486msec)
      # slat:提交延迟,这是提交I/O所花费的时间
    slat (usec): min=2, max=996, avg= 4.61, stdev= 4.55
    # clat: 完成延迟,提交之后,处理所花的时间
    clat (usec): min=40, max=1141.2k, avg=867.03, stdev=5649.13
    # 响应时间
     lat (usec): min=43, max=1141.2k, avg=871.72, stdev=5649.52
    # percentiles: 在性能测试中表示Top Percentile,简写TP,是一个统计学中的术语,与平均数,中位数等是同一类
    # 常见的参数是TP50, TP80, TP95
    # 举例:TP95:统计该方法每次调用所消耗的时间,并将这些时间按从小到大的顺序进行排序,取第95%的那个值作为TP95的值
    # 如下看到TP95的值是2057,则表示完成延迟的所有测试统计数据中,95%的测试消耗时间都是小于2057微秒,TP95=2057微秒
    clat percentiles (usec):
     |  1.00th=[  306],  5.00th=[  334], 10.00th=[  359], 20.00th=[  408],
     | 30.00th=[  445], 40.00th=[  482], 50.00th=[  515], 60.00th=[  553],
     | 70.00th=[  594], 80.00th=[  660], 90.00th=[ 1270], 95.00th=[ 2057],
     | 99.00th=[13698], 99.50th=[15139], 99.90th=[18482], 99.95th=[21365],
     | 99.99th=[69731]
   # bw: 磁盘带宽统计
   bw (  KiB/s): min= 2304, max=244152, per=100.00%, avg=149114.40, stdev=43253.75, samples=280
   # IOPS: 全称Input/Output Operations Per Second, 表示每秒的读/写次数
   # 由于处于read分组下面,所以在这边表示为读的次数
   iops        : min=  576, max=61038, avg=37278.60, stdev=10813.44, samples=280
  
  # 响应时间的latency分布信息,从最低延迟微秒逐步统计到以毫秒作为基本单位的延迟分布情况
  # 目测了一下,下面整块的分布百分比全部加起来是100%
  # 举例:下面的750=40.05%表示有40.05%的延迟是小于750微秒,但是大于500微秒
  # 举例:下面的4=4.44% 表示有4.44%的延迟小于4毫秒但是大于2毫秒
  lat (usec)   : 50=0.01%, 100=0.01%, 250=0.27%, 500=45.53%, 750=40.05%
  lat (usec)   : 1000=2.75%
  lat (msec)   : 2=5.64%, 4=4.44%, 10=0.09%, 20=1.17%, 50=0.05%
  lat (msec)   : 100=0.01%, 250=0.01%, 1000=0.01%, 2000=0.01%
  # cpu信息统计 usr:用户态CPU占用率,sys:系统CPU占用率,ctx:进程上下文切换次数
  # majf:major page faults 主要页面错误数量, minf: minor page faults 次要页面错误数量
  cpu          : usr=4.72%, sys=10.22%, ctx=2082417, majf=0, minf=34
  # IO depths: I/O深度在测试中的分布,控制同一个时刻有多少IO发送给系统
  # 该输出和命令执行时候的-iodepth参数有关
  IO depths    : 1=0.1%, 2=0.1%, 4=0.1%, 8=0.1%, 16=100.0%, 32=0.0%, >=64=0.0%
       # submit和complete代表同一时间段内fio发送和已完成的IO数量
     submit    : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.0%, 32=0.0%, 64=0.0%, >=64=0.0%
     complete  : 0=0.0%, 4=100.0%, 8=0.0%, 16=0.1%, 32=0.0%, 64=0.0%, >=64=0.0%
     # issued rwt: 发出的read/write/trim(裁剪)请求的数量,以及其中有多少请求被缩短或删除
     # 这个地方和官方文档上对不上,官方文档只有三个参数0,0,0,目前第四个参数位置意思不详
     issued rwts: total=2621440,0,0,0 short=0,0,0,0 dropped=0,0,0,0
     # 下面一行取决于命令执行配置的参数latency_target,latency_window,latency_percentile
     # 下面percentile=100% 表示该最大限度的使用磁盘速度
     latency   : target=0, window=0, percentile=100.00%, depth=16

Run status group 0 (all jobs):
   # bw: 该组中线程的总带宽,后跟该组中所有线程的最小和最大带宽
   # io: 该组中所有线程执行的聚合I/O
   # run:这组线程中最小和最长的运行时间统计
   READ: bw=143MiB/s (150MB/s), 143MiB/s-143MiB/s (150MB/s-150MB/s), io=10.0GiB (10.7GB), run=71486-71486msec

Disk stats (read/write):
  # sda(创建的文件夹位于sda,所以获取到该磁盘信息)
  # dm-0(dm-0可能是创建的文件夹的磁盘别名)磁盘上面的统计
  # ios:所有组队io次数统计,比如下面的数据表示input=2621440, output=0
  # merge: I/O调度器执行的总合并数
  # ticks: 使磁盘繁忙的滴答数
  # in_queue: 在磁盘队列中花费的总时间
  # util:磁盘速度利用率,值为99.06%表示在命令执行的99.06%时间内磁盘一直很忙
  # aggr开头的表示聚合后的统计,该值会比前面的没聚合的大一些
  dm-0: ios=2621375/19, merge=0/0, ticks=180184/0, in_queue=180184, util=99.23%, aggrios=2621441/13, aggrmerge=0/6, aggrticks=174973/3, aggrin_queue=174976, aggrutil=99.06%
  sda: ios=2621441/13, merge=0/6, ticks=174973/3, in_queue=174976, util=99.06%

使用fio如果不幸指定了filename参数的解决方案

看见别人挨打踩坑的时候一定要睁大眼睛,这样既能够学习到很多东西,又不用付出惨痛的代价

指定了非系统盘的解决方案

之前指定了-filename=/dev/sda作为参数,机器在重启之后不能正常进入gui界面,在等待了2分钟之后直接跳转到了系统恢复模式的终端

这个时候需要先去检查/etc/fstab文件,查看是否配置了/dev/sda盘的挂载项,发现使用了/dev/sda3挂载为swap分区,使用了/dev/sda4挂载到/home/gong/files

$ cat /etc/fstab 
// --snip--
# swap was on /dev/sda3 during installation
UUID=d365f79f-5cd3-43fa-a5cb-82d6eb2e9d55 none            swap    sw              0       0
# /home/gong/files on /dev/sda4 by user
UUID=5d642ccd-3905-46ec-b3e4-6ec4d30c6248 /home/gong/files  ext4  defaults        0       2


# 把上面的挂载项注释,修改为如下,保存之后重启系统,就可以正常进入系统了,磁盘修复后面再说
// --snip--
# swap was on /dev/sda3 during installation
#UUID=d365f79f-5cd3-43fa-a5cb-82d6eb2e9d55 none            swap    sw              0       0
# /home/gong/files on /dev/sda4 by user
#UUID=5d642ccd-3905-46ec-b3e4-6ec4d30c6248 /home/gong/files  ext4  defaults        0       2

进入系统后执行磁盘修复命令,发现程序不能识别该块磁盘的类型,需要指定超级块来运行

$ fsck -y /dev/sda
fsck,来自 util-linux 2.37.2
e2fsck 1.46.5 (30-Dec-2021)
ext2fs_open2:超级块中的幻数有错
fsck.ext2:超级块无效,正在尝试备份块...
fsck.ext2: 超级块中的幻数有错 尝试打开 /dev/sda 时

超级块无法被读取,或它未能正确地描述一个有效的 ext2/ext3/ext4 文件系统。
如果设备有效并确实为 ext2/ext3/ext4 文件系统(而非 swap 或 ufs 等格式),
这说明超级块已经损坏,您可能需要指定备选超级块来运行 e2fsck:
    e2fsck -b 8193 <设备>
 或
    e2fsck -b 32768 <设备>

按照提示执行如下命令

$ e2fsck -b 8193 /dev/sda

以及

$ e2fsck -b 32768 /dev/sda

发现执行的输出都是一样的,输出如下

e2fsck 1.46.5 (30-Dec-2021)
e2fsck: 超级块中的幻数有错 尝试打开 /dev/sda 时

超级块无法被读取,或它未能正确地描述一个有效的 ext2/ext3/ext4 文件系统。
如果设备有效并确实为 ext2/ext3/ext4 文件系统(而非 swap 或 ufs 等格式),
这说明超级块已经损坏,您可能需要指定备选超级块来运行 e2fsck:
    e2fsck -b 8193 <设备>
 或
    e2fsck -b 32768 <设备>

查看超级块的信息

$ mke2fs -n /dev/sda
mke2fs 1.46.5 (30-Dec-2021)
创建含有 117212886 个块(每块 4k)和 29310976 个 inode 的文件系统
文件系统 UUID:018cece1-d340-47e2-a3e3-ea505d6d7699
超级块的备份存储于下列块: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
    102400000

可以看到超级块存储的位置列表,是32768, 98304, 163840, 229376...,所以接下去需要历遍这些块

$ e2fsck -b 32768 /dev/sda
$ e2fsck -b 98304 /dev/sda
$ e2fsck -b 163840 /dev/sda
$ e2fsck -b 229376 /dev/sda

如果上述步骤都没用的话,清空硬盘格式化,重新开始

从零开始方案如下

清空该硬盘

$ sudo dd if=/dev/zero of=/dev/sda

创建为ext4类型的硬盘

$ sudo mkfs.ext4 /dev/sda 
mke2fs 1.46.5 (30-Dec-2021)
丢弃设备块: 完成                            
创建含有 117212886 个块(每块 4k)和 29310976 个 inode 的文件系统
文件系统 UUID:11072eb4-18af-473e-bb69-6d16cedb0083
超级块的备份存储于下列块: 
    32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208, 
    4096000, 7962624, 11239424, 20480000, 23887872, 71663616, 78675968, 
    102400000

正在分配组表: 完成                            
正在写入 inode表: 完成                            
创建日志(262144 个块): 完成
写入超级块和文件系统账户统计信息: 已完成   

最后挂载

$ sudo mount /dev/sda /home/gong/files

检查挂载结果

$ df -h
// --snip--

/dev/sda        440G   28K  417G    1% /home/gong/files

配置开机自动挂载

首先要查下设备的UUID参数

$ blkid |grep /dev/sda
/dev/sda: UUID="11072eb4-18af-473e-bb69-6d16cedb0083" BLOCK_SIZE="4096" TYPE="ext4"

最后编辑/etc/fstab文件,增加一行,UUID参数对应上面查询出来的结果

# <file system>                           <mount point>   <type> <options>    <dump>  <pass>

UUID=11072eb4-18af-473e-bb69-6d16cedb0083 /home/gong/files  ext4  defaults        0       2

不同位置的参数解释

  • <file system>: 要挂载分区的文件系统,此处建议使用UUID
  • <mount point>: 挂载点,自定义创建的一个文件夹的位置
  • <type> : 要挂载分区的文件系统类型, 使用blkid命令查询分区的文件系统类型
  • <options>: 挂载时使用的参数,一般情况下使用defaults参数就行
  • <dump> : 是否对这个文件系统进行备份, 0忽略,1备份
  • <pass>: fsck检查文件系统的优先级,一般情况下,可以设置为0

    • 0:表示不检查文件系统
    • 1:如果需要检查,根目录(/)对应的文件系统设置为1
    • 2:如果需要检查,非根目录对应的其它文件系统设置为2

参考阅读

Intel时钟速度说明

CPU工作方式、多核心、超线程技术详解

linux内存buff/cache的区别

详解Linux内核设备驱动,块设备概念和框架原理

Linux下磁盘IO读写测试工具-FIO详解

捋一捋磁盘及分区

fstab文件详解


龚正阳
29 声望5 粉丝

粗犷型程序员