Linux 是怎样工作的

武内觉

Posted by LXG on August 7, 2024

M.2 固态硬盘的两种类型:SATA 和 NVMe

查看系统调用命令 strace

strace -T 命令, 能以微秒级的精度来采集各种系统调用所消耗的时间


$ strace -T ./hello
execve("./hello", ["./hello"], 0x7ffdd7a60a68 /* 58 vars */) = 0 <0.000205>
brk(NULL)                               = 0x56a3bc7d2000 <0.000008>
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffc5e9b5850) = -1 EINVAL (无效的参数) <0.000007>
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x72e8e932c000 <0.000011>

---------------------省略------------------------

brk(0x56a3bc7f3000)                     = 0x56a3bc7f3000 <0.000007>
write(1, "Hello, World!\n", 14Hello, World!
)         = 14 <0.000008>
exit_group(0)                           = ?
+++ exited with 0 +++

sar 命令

获取CPU内核和用户态的时间

显示每个CPU核心的使用情况 : sar -P ALL 1 5 显示CPU平均使用情况: sar -P all 1


$ sar -P all 1
Linux 6.5.0-45-generic (lixiaogang) 	2024年08月07日 	_x86_64_	(32 CPU)

17时07分14秒     CPU     %user     %nice   %system   %iowait    %steal     %idle
17时07分15秒     all      3.18      0.00      0.25      0.09      0.00     96.48
17时07分16秒     all      3.71      0.00      0.25      0.00      0.00     96.04
17时07分17秒     all      3.18      0.00      0.28      0.06      0.00     96.47
17时07分18秒     all      3.13      0.00      0.16      0.16      0.00     96.56
^C

平均时间:     all      3.30      0.00      0.23      0.08      0.00     96.3

当 %system 的值高达几十时, 大多数是陷入了系统调用发起过多, 或者系统负载过高等糟糕的状态

查看程序依赖的库-ldd


$ ldd /usr/bin/ls
	linux-vdso.so.1 (0x00007ffd5bfc6000)
	libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007ad852d06000)
	libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007ad852a00000)
	libpcre2-8.so.0 => /lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007ad852c6f000)
	/lib64/ld-linux-x86-64.so.2 (0x00007ad852d72000)

libc.so 指的就是C语言标准库

OS 提供的程序

  • 初始化系统: init
  • 变更系统运行方式: sysctl sync
  • 文件操作: touch mkdir
  • 文本数据处理: grep sort
  • 性能测试: sar iostat
  • 编译: gcc
  • 脚本运行环境: python
  • shell: bash
  • 视窗系统: X

进程管理

fork() 启动子进程

execve() 启动新的进程

进程调度器

  • 不管同时运行多少个进程, 在任意时间点上, 只能有一个进程运行在逻辑CPU上
  • 在逻辑CPU上运行多个进程时, 它们将按轮询调度的方式循环运行
  • 每个进程分配到的时间片的长度大体上相等

超线程技术(Hyper-Threading Technology,简称 HT 或 HTT)是由英特尔公司开发的一项技术,它允许一个物理处理器核心同时执行多个线程,从而提高了处理器的并行计算能力和效率

进程上下文切换

进程的状态

  • 运行态: 正在逻辑CPU上运行
  • 就绪态: 等待CPU分配时间
  • 睡眠态: 进程不消耗CPU时间
  • 僵死状态: 等待父进程将其回收

睡眠状态的进程所等待的事件有以下几种

  • 等待指定的时间
  • 等待用户输入
  • 等待HDD或者SDD等外部存储器的读写结束
  • 等待网络的数据收发结束

逻辑CPU空闲状态idle


$ cat /proc/stat

cpu <user> <nice> <system> <idle> <iowait> <irq> <softirq> <steal> <guest> <guest_nice>
cpu  1268   182    1529    3043385 776     3183    298        0      0         0
cpu0 93 19 265 379185 43 1073 82 0 0 0
cpu1 105 16 475 377474 37 1904 118 0 0 0
cpu2 51 8 102 381174 41 132 12 0 0 0
cpu3 53 12 92 381321 60 48 7 0 0 0
cpu4 244 34 195 380999 136 6 6 0 0 0
cpu5 205 11 114 381178 155 4 2 0 0 0
cpu6 275 28 155 380996 142 6 64 0 0 0
cpu7 239 50 128 381054 157 8 3 0 0 0
intr 5170192 0 94441 141236 0 0 2678 1107 0 0 0 0 0 0 4770244 71948 0 2 829 1 2652 0 0 34 0 0 2 2 864 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7389 29805 0 0 492 0 0 0 0 68 0 1298 0 0 0 0 36898 23 92 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 8072 0 0 0 0 13 0 0 0 0 0 0 0 0 0 0 0 0 0
ctxt 8169492
btime 1721879463
processes 1920
procs_running 1
procs_blocked 0
softirq 809562 18 120715 1 0 12971 0 5671 643876 0 26310

top -n 1


Tasks: 269 total,   1 running, 268 sleeping,   0 stopped,   0 zombie
  Mem:  7848664K total,  1950332K used,  5898332K free,     3664K buffers
 Swap:  3924328K total,        0K used,  3924328K free,   998748K cached
800%cpu   0%user   0%nice   4%sys 792%idle   0%iow   4%irq   0%sirq   0%host
  PID USER         PR  NI VIRT  RES  SHR S[%CPU] %MEM     TIME+ ARGS
 1923 shell        20   0  10G 4.2M 3.4M R  3.8   0.0   0:00.01 top -n 1
 1917 root          0 -20    0    0    0 I  0.0   0.0   0:00.00 [kworker/3:1H]

吞吐量 = 处理完成的进程数量 / 耗费的时间 延迟 = 结束处理的时间 - 开始处理的时间

  • 在耗尽逻辑CPU的计算能力后(无空闲状态), 不管继续增加多少个进程吞吐量都不会发生变化
  • 随着进程数量的增加, 延迟会越来越长
  • 每个进程的平均延迟是相等的

多个逻辑CPU的负载均衡和全局调度

运行时间和执行时间

$ time ls

real	0m0.002s
user	0m0.002s
sys	0m0.000s

$ time sleep 10

real	0m10.006s
user	0m0.000s
sys	0m0.001s

内存管理

内存采集命令


$ free -h
               total        used        free      shared  buff/cache   available
内存:       62Gi       9.2Gi        23Gi       478Mi        29Gi        52Gi
交换:      8.0Gi          0B       8.0Gi


$ sar -hr 1
Linux 6.5.0-45-generic (lixiaogang) 	2024年08月08日 	_x86_64_	(32 CPU)

15时40分46秒 kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
15时40分47秒     23.5G     52.4G      8.6G     13.8%      6.0G     19.3G     30.3G     42.9%     10.9G     22.6G    492.0k
15时40分48秒     23.5G     52.4G      8.6G     13.8%      6.0G     19.3G     30.3G     42.9%     10.9G     22.6G    492.0k

虚拟内存

文件映射

请求分页

mmap() 函数请求分页时, 可能引发物理内存不足的问题

sar -B 1 查看却页中断次数 fault/s

  • pgpgin/s:每秒从磁盘读入物理内存的页数。
  • pgpgout/s:每秒从物理内存写入磁盘的页数。
  • fault/s:每秒发生的缺页中断次数。这表示程序请求访问的页面不在物理内存中,必须从磁盘加载。
  • majflt/s:每秒发生的重大缺页中断次数。这通常发生在程序试图访问不在物理内存中的页面,并且该页面需要从磁盘加载到内存中。
  • pgfree/s:每秒释放的空闲页数。
  • pgscank/s:每秒扫描的页面数。这是系统为了寻找空闲页而扫描的页面数。
  • pgscand/s:每秒通过扫描空闲列表释放的页面数。
  • pgsteal/s:每秒从其他进程偷取的页面数。这通常发生在内存压力大时,系统从一个进程那里抢占页面分配给另一个进程。
  • %vmeff:虚拟内存效率百分比。这是衡量系统使用虚拟内存的有效程度的指标。如果这个值接近 0%,则表示系统有效地使用了虚拟内存;如果接近 100%,则表示系统频繁地进行页面交换,这可能会影响性能。

$ sar -B 1
Linux 6.5.0-45-generic (lixiaogang) 	2024年08月08日 	_x86_64_	(32 CPU)

17时02分47秒  pgpgin/s pgpgout/s   fault/s  majflt/s  pgfree/s pgscank/s pgscand/s pgsteal/s    %vmeff
17时02分48秒   3396.00      0.00   1356.00      0.00  12137.00      0.00      0.00      0.00      0.00
17时02分49秒   3376.00   4620.00   2125.00      0.00  11100.00      0.00      0.00      0.00      0.00
17时02分50秒   3956.00   5612.00   1333.00      0.00  11311.00      0.00      0.00      0.00      0.00
17时02分51秒   8180.00   4676.00   2711.00      0.00  11841.00      0.00      0.00      0.00      0.00

写时复制

物理内存并非在发起fork()系统调用时进行复制, 而是在尝试写入时才进行复制

交换分区

当系统长期内存不足时, 访问内存的操作将导致页面不断的换入和换出, 从而导致系统陷入抖动状态


$ swapon --show
NAME      TYPE SIZE USED PRIO
/swapfile file   8G   0B   -2

$ sar -W 1
Linux 6.5.0-45-generic (lixiaogang) 	2024年08月08日 	_x86_64_	(32 CPU)

17时52分43秒  pswpin/s pswpout/s
17时52分44秒      0.00      0.00
17时52分45秒      0.00      0.00

多级页表

标准大页

存储层次

  • 寄存器
  • 高速缓存
  • 内存
  • 外部存储器

高速缓存

  1. 根据指令, 将数据从内存读取到寄存器
  2. 基于寄存器上的数据进行计算
  3. 将运算结果写入内存

对于计算机系统来说, 无论流程2有多快, 流程 1 和 流程 3 都会成为性能瓶颈, 整体的速度受限于内存的访问延迟, 高速缓存的存在就是为了抹平寄存器和内存之间的性能差距

当高速缓存不足时会发生抖动, lscpu 命令查看高速缓存

rk3588 高速缓存

  • Integrated 64KB L1 instruction cache, 64KB L1 data cache and 512KB L2 cache for each Cortex-A76
  • Integrated 32KB L1 instruction cache, 32KB L1 data cache and 128KB L2 cache for each Cortex-A55
  • Quad-core Cortex-A76 and Quad-core Cortex-A55 share 3MB L3 cache

rk3568 高速缓存

  • Integrated 32KB L1 instruction cache, 32KB L1 data cache with ECC
  • 512KB unified system L3 cache with ECC

rk3399 高速缓存

  • Each Cortex-A72 integrates48KB L1 instruction cache and 32KB L1 data cache with 4- way set associative.
  • Each Cortex A53 integrates 32KB L1 instruction cache and 32kB L1 data cache separately with 4-way set associative
  • 1MB unified L2 Cache for Big cluster, 512KB unified L2 Cache for Little cluster

全志A133高速缓存

  • 32 KB L1 Instruction cache and 32 KB L1 Data cache for per CPU
  • 512 KB L2 cache shared

多级缓存


$ lscpu
架构:                   x86_64
  CPU 运行模式:         32-bit, 64-bit
  Address sizes:         48 bits physical, 48 bits virtual
  字节序:               Little Endian
CPU:                     32
  在线 CPU 列表:        0-31
厂商 ID:                AuthenticAMD
  型号名称:             AMD Ryzen 9 5950X 16-Core Processor
    CPU 系列:           25
    型号:               33
    每个核的线程数:     2
    每个座的核数:       16
    座:                 1
    步进:               2
    Frequency boost:     enabled
    CPU 最大 MHz:       5083.3979
    CPU 最小 MHz:       2200.0000
    BogoMIPS:           6787.70
Virtualization features: 
  虚拟化:               AMD-V
Caches (sum of all):
  L1d:                   512 KiB (16 instances) (每核心)(数据)
  L1i:                   512 KiB (16 instances) (每核心)(指令)
  L2:                    8 MiB (16 instances)  (每核心)
  L3:                    64 MiB (2 instances) (共享)

访问局部性

  • 时间局部性
  • 空间局部性

转译后备缓冲区

CPU 上存在一个具有与高速缓存同样访问速度的区域, 名为转译后备缓冲区(TLB), 又称为快表或者页表缓冲, 用来保存虚拟地址和物理地址的转换表

页面缓存

页面缓存是将外部存储器上的文件数据缓存到内存上

只要系统上还存在可用内存, 则每当各个进程访问那些尚未读取到页面缓存的文件时, 页面缓存的大小就会随之增大

当系统内存不足时, 内核将释放页面缓存以空出可用内存, 先丢弃脏页以外的页面, 如果仍然内存不足, 就会将脏页数据写回外部存储, 然后释放

笔者自己的台式机32GB内存编译android 11系统时内存很容易满, 此时就触发了脏页的回写,导致系统性能急剧下降, 更换成64G内存后好的多了

同步写入

为了避免突然断电导致的脏页数据丢失, 可以在open()系统调用打开文件时, 将flag参数设置为O_SYNC, 这样每当写文件时, 数据会同步写入外部存储器

调优参数


$ sysctl -a | grep dirty

# 以字节为单位(默认不启用)
vm.dirty_background_bytes = 0

# 当脏页占用的内存量和系统调用内存总量比例到10%时, 系统开始向外部存储回写
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0

# 脏页面的有效期限为30秒, 单位是百分之一秒
vm.dirty_expire_centisecs = 3000

# 当脏页的内存占比超过20%时, 将阻塞进程的写入, 直到一定量的脏页完成回写处理
vm.dirty_ratio = 20

# 每5秒向外部存储器执行一次回写
vm.dirty_writeback_centisecs = 500

vm.dirtytime_expire_seconds = 43200


rk3399 android 7


$ sysctl -a | grep dirty

vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 5
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 200
vm.dirty_ratio = 20
vm.dirty_writeback_centisecs = 500
vm.dirtytime_expire_seconds = 43200


超线程

访问内存的延迟比CPU运算消耗的时间长的多, 通过time命令显示的计入user和sys的CPU使用时间中, 大部分浪费在了等待数据从内存或者告诉缓存传输到CPU的过程

linux_cpu

top命令查看到的CPU使用率同样包含等待数据传输的时间, 通过超线程, 可以有效利用这些浪费的CPU资源

文件系统

  • 执行内核中全部文件系统通用处理, 并判断操作对象的文件保存在哪个文件系统上
  • 调用文件系统专有的处理, 并执行与请求的系统调用对应的处理
  • 调用设备驱动程序执行读写操作

数据和元数据


$ df -h
文件系统        大小  已用  可用 已用% 挂载点
tmpfs           6.3G  2.2M  6.3G    1% /run
/dev/nvme0n1p2  916G  122G  747G   15% /
tmpfs            32G  174M   32G    1% /dev/shm
tmpfs           5.0M  4.0K  5.0M    1% /run/lock
efivarfs        128K   44K   80K   36% /sys/firmware/efi/efivars
/dev/nvme0n1p1  511M  6.1M  505M    2% /boot/efi
/dev/sda        7.3T  3.4T  3.5T   50% /home/lxg/code
tmpfs           6.3G  180K  6.3G    1% /run/user/1000

------rk3399 android 7------------

rk3399_all:/ $ df -h
Filesystem            Size  Used Avail Use% Mounted on
rootfs                1.8G  4.7M  1.8G   1% /
tmpfs                 1.8G  436K  1.8G   1% /dev
tmpfs                 1.8G     0  1.8G   0% /mnt
/dev/block/dm-0       1.4G  0.9G  358M  74% /system
/dev/block/mmcblk1p9  122M  520K  113M   1% /cache
/dev/block/mmcblk1p11  12M   52K   11M   1% /metadata
tmpfs                 1.8G     0  1.8G   0% /storage
/dev/block/dm-1        55G  472M   55G   1% /data
/data/media            55G  616M   55G   2% /storage/emulated


文件系统不一致问题

比如文件系统变更时突然断电, 如果挂载时检测到不一致,则可能会以只读模式重新挂载系统, 最坏的情况下可能导致系统出错

安卓系统在处理断电导致的文件系统不一致问题时,通常会采取以下几种方法:

  • 日志文件系统(Journaling File System):安卓使用的许多文件系统(如ext4)是日志文件系统,它会在写入数据之前先记录一份日志。这样,在系统意外断电后,可以通过日志来恢复到一致的状态,避免文件损坏。
  • 原子操作(Atomic Operations):在执行文件操作时,安卓会尽量保证这些操作是原子的,即要么全部完成,要么完全不执行。这样可以减少因中断而导致的文件不一致问题。
  • 数据备份和恢复:在执行重要的写入操作之前,系统会先备份相关数据,确保在操作失败时能够恢复到之前的状态。
  • 定期检查和修复文件系统:安卓系统可以定期执行文件系统检查,识别并修复不一致的文件。这通常在设备启动时进行。
  • 使用缓存机制:在数据写入过程中,安卓系统会使用缓存来暂存数据,并在合适的时机将其写入实际的存储介质。这可以减少写入次数,提高效率,同时降低数据丢失的风险。

文件种类

  • 字符设备
  • 块设备

字符设备

字符设备虽然能执行读写操作, 但是无法自行确定读取数据的位置

  • 终端
  • 鼠标
  • 键盘

块设备

块设备除了能执行普通的读写操作外, 还能进行随机访问, 通常不会直接访问块设备, 而是在设备上创建一个文件系统并将其挂载, 然后通过文件系统进行访问, 以下几种情况下, 需要直接操作块儿设备

  • 更新分区表
  • 块设备级别的数据备份和还原
  • 创建文件系统
  • 挂载文件系统

基于内存的文件系统

tmpfs 是一种创建于内存上的文件系统. 访问速度快, android 上的dev 和 dev 目录, 就是tmpfs文件系统


rk3399_all:/ $ df
Filesystem            1K-blocks    Used Available Use% Mounted on
rootfs                  1958316    4816   1953500   1% /
tmpfs                   1967896     436   1967460   1% /dev
tmpfs                   1967896       0   1967896   0% /dev
/dev/block/dm-0         1499760 1038920    367044  74% /system
/dev/block/mmcblk1p9     124912     520    115220   1% /cache
/dev/block/mmcblk1p11     12016      52     10824   1% /metadata
/dev/block/dm-1        58013380  485192  57380732   1% /data
/data/media            57910980  632648  57278332   2% /storage/emulated


rk3399_all:/ $ mount | grep tmpfs
tmpfs on /dev type tmpfs (rw,seclabel,nosuid,relatime,size=1967896k,nr_inodes=491974,mode=755)
tmpfs on /mnt type tmpfs (rw,seclabel,relatime,size=1967896k,nr_inodes=491974,mode=755,gid=1000)
tmpfs on /storage type tmpfs (rw,seclabel,relatime,size=1967896k,nr_inodes=491974,mode=755,gid=1000)

Linux


$ mount | grep tmpfs
udev on /dev type devtmpfs (rw,nosuid,relatime,size=32818224k,nr_inodes=8204556,mode=755,inode64)
tmpfs on /run type tmpfs (rw,nosuid,nodev,noexec,relatime,size=6571396k,mode=755,inode64)
tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev,inode64)
tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k,inode64)
tmpfs on /run/snapd/ns type tmpfs (rw,nosuid,nodev,noexec,relatime,size=6571396k,mode=755,inode64)
tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=6571392k,nr_inodes=1642848,mode=700,uid=1000,gid=1000,inode64)

tmpfs 创建于挂载的时候, 在挂载时, 通过size选项指定最大容量. 不过并不是说从一开始就占用指定的内存量, 而是在初次访问文件系统中的区域时, 以页为单位申请相应大小的内存. 通过free命令的输出结果中shared 字段的值, 可以得到tmpfs的内存占用量


1|rk3399_all:/ $ free -h
		total        used        free      shared     buffers
Mem:             3.7G        1.1G        2.5G        110M         20M
-/+ buffers/cache:           1.1G        2.6G
Swap:            509M           0        509M

网络文件系统

虽然网络文件系统种类很多, 但是访问远程windows主机上的文件时, 使用名为cifs的文件系统, 访问远程是Linux等类UNIX主机上的文件时,使用NFS的文件系统

虚拟文件系统

procfs 用于获取系统上所有进程的信息


asound: 音频子系统的配置信息
bluetooth: 蓝牙设备的相关信息
buddyinfo: 
bus : 系统总线类型及其所连接设备的信息
cgroups: 控制组(Control Groups)的信息,用于资源管理和限制。
cmdline : 引导时传递给内核的命令行参数
config.gz : 当前内核配置文件的压缩版本
consoles : 系统控制台的信息
cpuinfo : CPU的相关信息
crypto : 加密算法和设备的信息
device-tree : 设备树信息,通常用于嵌入式系统
devices : 系统中的硬件设备列表
diskstats : 磁盘I/O统计信息
driver : 驱动程序的信息
execdomains : 执行域信息,用于内存保护
fb : 显示设备的信息
filesystems : 支持的文件系统列表
fs : 文件系统相关信息
iep : 内存管理器信息
interrupts : 中断请求(IRQ)的信息
iomem : I/O内存映射区域
ioports : I/O端口的使用情况
irq : 中断请求(IRQ)控制器的详细信息
kallsyms : 内核符号表
key-users : 与用户相关的密钥信息
keys : 用户空间密钥环的信息
kmsg : 内核消息缓冲区,可以用来查看内核日志
kpagecgroup : 与页面缓存相关的控制组信息
kpagecount : 物理页框的计数信息
kpageflags : 物理页框的标志信息
loadavg : 系统负载平均值
locks : 锁的信息,包括内核锁
meminfo : 内存使用情况的概览
misc : 各种杂项设备的信息
modules : 已加载的内核模块列表
mounts : 系统上的挂载点信息
net : 网络子系统的配置信息
pagetypeinfo : 页面类型的详细信息
partitions : 系统磁盘分区信息c
sched_debug : 调度器调试信息
schedstat : 进程调度统计信息
scsi : SCSI设备信息
self
softirqs : 软中断信息
stat : 系统统计信息
swaps : 交换分区的状态
sys : 系统配置信息
sysrq-trigger : 系统请求键触发功能
thread-self
timer_list : 定时器列表
timer_stats : 定时器统计数据
tty : 终端设备信息
uid_cputime : 用户ID相关的CPU使用时间统计
uid_io : 用户ID相关的I/O操作统计
uid_procstat : 用户ID相关的进程状态统计
uptime : 系统运行时间
version : 内核版本信息
vmallocinfo
vmstat :  虚拟内存统计信息
zoneinfo : 内存管理区域的信息

sys 文件系统

为了防止procfs的滥用, Linux 又引入了一个名为sysfs的文件系统


rk3399_all:/ $ ls -1 sys
block : 包含块设备的信息,如硬盘、USB 存储设备
bus : 包含各种总线类型及其所连接设备的信息,如 PCI、USB 等
camera_test : 相机测试
class : 包含设备类别的信息,例如字符设备、块设备等
dev : 包含设备文件的符号链接
devices : 包含设备文件的符号链接
firmware : 包含系统中所有硬件设备信息
fs : 包含文件系统相关信息
kernel : 包含内核相关信息
module : 包含已加载内核模块的信息
power : 包含电源管理相关信息
rk8xx :

cgroupfs文件系统

cgroupfs 用于限制单个进程或者由多个进程组成的群组的资源使用量, 通常挂载在sys/fs/cgroup目录下

cgroup 通常被用于通过Docker之类的容器管理软件, 或者虚拟机软件来限制各个容器或者虚拟机的资源使用量.


$ ls -1 /sys/fs/cgroup/
cgroup.controllers
cgroup.max.depth
cgroup.max.descendants
cgroup.pressure
cgroup.procs
cgroup.stat
cgroup.subtree_control
cgroup.threads
cpu.pressure
cpuset.cpus.effective
cpuset.mems.effective
cpu.stat
dev-hugepages.mount
dev-mqueue.mount
init.scope
io.cost.model
io.cost.qos
io.pressure
io.prio.class
io.stat
memory.numa_stat
memory.pressure
memory.reclaim
memory.stat
misc.capacity
misc.current
proc-sys-fs-binfmt_misc.mount
sys-fs-fuse-connections.mount
sys-kernel-config.mount
sys-kernel-debug.mount
sys-kernel-tracing.mount
system.slice
user.slice

Btrfs文件系统

Btrfs 是一种新型的 写时复制 ( Copy on Write ) Linux 文件系统,已经并入内核主线。Btrfs 在设计实现高级功能的同时,着重于 容错 、 修复 以及易于 管理

外部存储器

HDD : 机械硬盘


sudo smartctl -a /dev/sda
smartctl 7.2 2020-12-30 r5155 [x86_64-linux-6.5.0-45-generic] (local build)
Copyright (C) 2002-20, Bruce Allen, Christian Franke, www.smartmontools.org

=== START OF INFORMATION SECTION ===
Device Model:     ST8000NM000A-2KE101
Serial Number:    WSD5VGDE
LU WWN Device Id: 5 000c50 0e096d392
Firmware Version: SC03
User Capacity:    8,001,563,222,016 bytes [8.00 TB]
Sector Sizes:     512 bytes logical, 4096 bytes physical
Rotation Rate:    7200 rpm
Form Factor:      3.5 inches
Device is:        Not in smartctl database [for details use: -P showall]
ATA Version is:   ACS-4 (minor revision not indicated)
SATA Version is:  SATA 3.3, 6.0 Gb/s (current: 6.0 Gb/s)
Local Time is:    Wed Aug 14 14:08:40 2024 CST
SMART support is: Available - device has SMART capability.
SMART support is: Enabled

SSD : 固态硬盘

sudo smartctl -a /dev/nvme0n1p2

<pre>=== START OF INFORMATION SECTION ===
Model Number:                       KINGSTON SNV2S1000G
Serial Number:                      50026B7784F86AF0
Firmware Version:                   SBI02102
PCI Vendor/Subsystem ID:            0x2646
IEEE OUI Identifier:                0x0026b7
Controller ID:                      1
NVMe Version:                       1.4
Number of Namespaces:               1
Namespace 1 Size/Capacity:          1,000,204,886,016 [1.00 TB]
Namespace 1 Formatted LBA Size:     512
Namespace 1 IEEE EUI-64:            0026b7 784f86af05
Local Time is:                      Wed Aug 14 14:12:17 2024 CST
Firmware Updates (0x12):            1 Slot, no Reset required
Optional Admin Commands (0x0016):   Format Frmw_DL Self_Test
Optional NVM Commands (0x009f):     Comp Wr_Unc DS_Mngmt Wr_Zero Sav/Sel_Feat Verify
Log Page Attributes (0x12):         Cmd_Eff_Lg Pers_Ev_Lg
Maximum Data Transfer Size:         64 Pages
Warning  Comp. Temp. Threshold:     83 Celsius
Critical Comp. Temp. Threshold:     90 Celsius
</pre>

Linux中将HDD和SSD这类可以随机访问, 并能以一定大小访问的设备统一归类为块设备

块设备可以通过设备文件直接访问, 也可以通过在其上构建的文件系统间接访问.

由于各种块设备的通用处理很多, 所以在设备驱动程序之上有个通用块层, 文件系统和设备文件访问都是通过通用块层访问磁盘

I/O调度器

通用块层的IO调度器会将访问块设备的请求积攒一段儿时间, 并在向设备驱动程序发出I/O请求之前对这些请求进行加工, 以提高性能

  • 合并: 将访问连续扇区的多个请求合并为一个
  • 排序: 按照扇区的序列号对访问不连续的扇区的多个请求进行排序

磁盘I/O调试

sar -d 1 1


DEV: 设备名称。
tps: 每秒传输的事务数 (transactions per second)。
rkB/s: 每秒从设备读取的千字节数 (read kilobytes per second)。
wkB/s: 每秒向设备写入的千字节数 (write kilobytes per second)。
dkB/s: 每秒从设备删除的千字节数 (discard kilobytes per second)。
areq-sz: 平均请求大小 (average request size)。
aqu-sz: 平均队列长度 (average queue size)。
await: 平均每次 I/O 操作的等待时间 (average time for I/O operations)。
%util: 设备的利用率 (device utilization)。

平均时间:       DEV       tps     rkB/s     wkB/s     dkB/s   areq-sz    aqu-sz     await     %util
平均时间:       sda    304.00  34512.00     12.00      0.00    113.57      3.95     12.79    100.00
平均时间:   nvme0n1    121.00    528.00    100.00      0.00      5.19      0.02      0.13      1.10