磁盘 I/O

磁盘 I/O

作者:赵坤

虚拟文件系统

I/O 调度

为了减小不同块设备的差异带来的影响,Linux 通过一个统一的通用块层,来管理各种不同的块设备。通用块层,其实是处在文件系统和磁盘驱动中间的一个块设备抽象层。它会给文件系统和应用程序发来的 I/O 请求排队,并通过重新排序、请求合并等方式,提高磁盘读写的效率。

Linux 内核支持四种 I/O 调度算法,分别是 NONENOOPCFQ 以及 DeadLine

  • NONE,不使用 I/O 调度算法
  • NOOP,先入先出
  • CFQ(Completely Fair Scheduler),为每个进程维护了一个 I/O 调度队列,并按照时间片来均匀分布每个进程的 I/O 请求
  • DeadLine,分别为读、写请求创建了不同的 I/O 队列,可以提高机械磁盘的吞吐量,并确保达到最终期限(deadline)的请求被优先处理

每块磁盘 I/O 性能

$ iostat -d -x 1
Linux 5.4.0-42-generic (zk) 	2020年09月02日 	_x86_64_	(4 CPU)

Device            r/s     rkB/s   rrqm/s  %rrqm r_await rareq-sz     w/s     wkB/s   wrqm/s  %wrqm w_await wareq-sz     d/s     dkB/s   drqm/s  %drqm d_await dareq-sz  aqu-sz  %util
loop0            0.67      0.73     0.00   0.00    0.59     1.08    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.01
loop1            0.01      0.06     0.00   0.00    0.87     7.43    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.00
loop2            0.23      0.28     0.00   0.00    0.40     1.24    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.01
loop3            1.49      1.55     0.00   0.00    0.40     1.04    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.02
loop4            0.87      1.05     0.00   0.00    0.46     1.21    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.01
loop5            0.01      0.06     0.00   0.00    0.64     8.05    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.00
loop6            2.20      2.25     0.00   0.00    0.47     1.02    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.03
loop7            0.00      0.00     0.00   0.00    0.00     1.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.00
sda              0.06      1.92     0.00   0.00   30.65    31.56    0.00      0.00     0.00   0.00    0.00     0.00    0.00      0.00     0.00   0.00    0.00     0.00    0.00   0.01
sdb              6.13    277.71     1.45  19.16    1.17    45.31    8.24    166.67     6.65  44.65    0.88    20.23    0.00      0.00     0.00   0.00    0.00     0.00    0.00   1.03

其中:

  • %util,就是磁盘 I/O 使用率;
  • r/s + w/s ,就是 IOPS;
  • rkB/s+wkB/s ,就是吞吐量;
  • r_await+w_await ,就是响应时间。

进程 I/O 性能

$ pidstat -d 1
Average:      UID       PID   kB_rd/s   kB_wr/s kB_ccwr/s iodelay  Command
Average:        0       282     -1.00     -1.00     -1.00       0  jbd2/sdb5-8
Average:     1000      2524      0.00     11.96      0.00       0  chrome

追踪系统调用

如何知道某个进程当前正在读写哪一个文件?


$ strace -p 18940 
strace: Process 18940 attached 
...
mmap(NULL, 314576896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0f7aee9000 
mmap(NULL, 314576896, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f0f682e8000 
write(3, "2018-12-05 15:23:01,709 - __main"..., 314572844 
) = 314572844 
munmap(0x7f0f682e8000, 314576896)       = 0 
write(3, "\n", 1)                       = 1 
munmap(0x7f0f7aee9000, 314576896)       = 0 
close(3)                                = 0 
stat("/tmp/logtest.txt.1", {st_mode=S_IFREG|0644, st_size=943718535, ...}) = 0 

查看进程打开的文件列表


$ lsof -p 18940 
COMMAND   PID USER   FD   TYPE DEVICE  SIZE/OFF    NODE NAME 
python  18940 root  cwd    DIR   0,50      4096 1549389 / 
python  18940 root  rtd    DIR   0,50      4096 1549389 / 
… 
python  18940 root    2u   CHR  136,0       0t0       3 /dev/pts/0 
python  18940 root    3w   REG    8,1 117944320     303 /tmp/logtest.txt 

软链接/硬链接

是什么

Linux 上的文件,数据和元信息是分开的,元信息比如说创建者、创建日期、文件大小、链接数、读/写/执行权限等,这种存储文件元信息的区域叫做 Inode。可以使用命令 stat 查看文件的元信息:

stat file.txt

每个 inode 都有一个号码,操作系统用这个号码识别 inode。可以使用 ls -i file.txt 直接查看这个号码。

磁盘空间有,但却无法创建文件

创建大量的空文件,可以把 inode 耗尽

硬链接

多个文件名指向同一个文件,删除这个不影响另外一个: ln filename [linkname],但是 inode 的 link 数会减少一个,rm 的时候链接数递减

软链接

相当于 Windows 中的快捷方式,软链接可以跨文件系统,可以对目录链接: ln -s filename [linkname],软链接有自己的 inode 和 data block,创建软链接,link 数不会增加。

文件 A 和文件 B 的 inode 号码虽然不一样,但是文件 A 的内容是文件 B 的路径。读取文件A时,系统会自动将访问者导向文件B。因此,无论打开哪一个文件,最终读取的都是文件B。

如果删除了文件B,打开文件A就会报错:“No such file or directory”。