本文主要以一张图为基础,向大家介绍 Linux在 I/O 上做了哪些事情,即 Linux 中直接 I/O 原理,希望本文的经验和思路能为读者提供一些帮助和思考。
在 Linux 中一切皆文件。不仅普通的文件和目录,就连块设备、套接字、管道等,也都要通过统一的文件系统来管理。
用 ls -l 命令看最前面的字符可以看到这个文件是什么类型brw-r--r-- 1 root root 1, 2 4月 25 11:03 bnod // 块设备文件crw-r--r-- 1 root root 1, 2 4月 25 11:04 cnod // 符号设备文件drwxr-xr-x 2 wrn3552 wrn3552 6 4月 25 11:01 dir // 目录-rw-r--r-- 1 wrn3552 wrn3552 0 4月 25 11:01 file // 普通文件prw-r--r-- 1 root root 0 4月 25 11:04 pipeline // 有名管道srwxr-xr-x 1 root root 0 4月 25 11:06 socket.sock // socket文件lrwxrwxrwx 1 root root 4 4月 25 11:04 softlink -> file // 软连接-rw-r--r-- 2 wrn3552 wrn3552 0 4月 25 11:07 hardlink // 硬链接(本质也是普通文件)
inode(index node):索引节点
dentry(directory entry):目录项
wrn3552@novadev:~/playground$ stat file 文件:file 大小:0 块:0 IO 块:4096 普通空文件设备:fe21h/65057d Inode:32828 硬链接:2权限:(0644/-rw-r--r--) Uid:( 3041/ wrn3552) Gid:( 3041/ wrn3552)最近访问:2021-04-25 11:07:59.603745534 +0800最近更改:2021-04-25 11:07:59.603745534 +0800最近改动:2021-04-25 11:08:04.739848692 +0800创建时间:-
dentry
wrn3552@novadev:~/playground$ tree.├── dir│ └── file_in_dir├── file└── hardlink
不同于 inode,dentry 是由内核维护的一个内存数据结构,所以通常也被叫做 dentry cache。
Superblock
inode blocks
data blocks
superblock 对于文件系统来说非常重要,如果 superblock 损坏了,文件系统就挂载不了了,相应的文件也没办法读写。既然 superblock 这么重要,那肯定不能只有一份,坏了就没了,它在系统中是有很多副本的,在 superblock 损坏的时候,可以使用 fsck(File System Check and repair)来恢复。回到上面的那张图,可以很清晰地看到文件的各种属性和文件的数据是如何存储在磁盘上的:
这里解释一下什么是 logical block:
/sys/block/sda/queue/physical_block_size
/sys/block/sda/queue/logical_block_size理论上应该是 logical_block_size >= physical_block_size,但是有时候我们会看到 physical_block_size = 4K,logical_block_size = 512B 情况,其实这是因为磁盘上做了一层 512B 的仿真(emulation)(详情可参考 512e 和 4Kn)
这是一张从底向上的图:
root@:~ # zpool create tank raidz /dev/ada1 /dev/ada2 /dev/ada3 raidz /dev/ada4 /dev/ada5 /dev/ada6root@:~ # zpool list tankNAME SIZE ALLOC FREE CKPOINT EXPANDSZ FRAG CAP DEDUP HEALTH ALTROOTtank 11G 824K 11.0G - - 0% 0% 1.00x ONLINE -root@:~ # zpool status tankpool: tankstate: ONLINEscan: none requestedconfig:NAME STATE READ WRITE CKSUMtank ONLINE 0 0 0raidz1-0 ONLINE 0 0 0ada1 ONLINE 0 0 0ada2 ONLINE 0 0 0ada3 ONLINE 0 0 0raidz1-1 ONLINE 0 0 0ada4 ONLINE 0 0 0ada5 ONLINE 0 0 0ada6 ONLINE 0 0 0
创建了一个名为 tank 的 zpool
这里的 raidz 同 RAID5
root@:~ # zfs create -o mountpoint=/mnt/srev tank/srevroot@:~ # df -h tank/srevFilesystem Size Used Avail Capacity Mounted ontank/srev 7.1G 117K 7.1G 0% /mnt/srev
对 zfs 设置 quota
root@:~ # zfs set quota=1G tank/srevroot@:~ # df -h tank/srevFilesystem Size Used Avail Capacity Mounted ontank/srev 1.0G 118K 1.0G 0% /mnt/srev
Pool 存储
上面的层级图和操作步骤可以看到 zfs 是基于 zpool 创建的,zpool 可以动态扩容意味着存储空间也可以动态扩容,而且可以创建多个文件系统,文件系统共享完整的 zpool 空间无需预分配。
事务文件系统
zfs 的写操作是事务的,意味着要么就没写,要么就写成功了,不会像其他文件系统那样,应用打开了文件,写入还没保存的时候断电,导致文件为空。zfs 保证写操作事务采用的是 copy on write 的方式:
ARC 缓存
ARC 定义了 4 个链表:
ARC 工作流程大致如下:
关于 ZFS 详细介绍可以参考:
这篇文章
磁盘根据不同的分类方式,有各种不一样的类型。
根据磁盘接口分类:
不同的接口,往往分配不同的设备名称。比如, IDE 设备会分配一个 hd 前缀的设备名,SCSI 和 SATA 设备会分配一个 sd 前缀的设备名。如果是多块同类型的磁盘,就会按照 a、b、c 等的字母顺序来编号。
g18-"299" on ~# ls -l /dev/sda*brw-rw---- 1 root disk 8, 0 Apr 25 15:53 /dev/sdabrw-rw---- 1 root disk 8, 1 Apr 25 15:53 /dev/sda1brw-rw---- 1 root disk 8, 10 Apr 25 15:53 /dev/sda10brw-rw---- 1 root disk 8, 2 Apr 25 15:53 /dev/sda2brw-rw---- 1 root disk 8, 5 Apr 25 15:53 /dev/sda5brw-rw---- 1 root disk 8, 6 Apr 25 15:53 /dev/sda6brw-rw---- 1 root disk 8, 7 Apr 25 15:53 /dev/sda7brw-rw---- 1 root disk 8, 8 Apr 25 15:53 /dev/sda8brw-rw---- 1 root disk 8, 9 Apr 25 15:53 /dev/sda9
下图是一个完整的 I/O 栈全景图:
使用率:ioutil,指的是磁盘处理 I/O 的时间百分比,ioutil 只看有没有 I/O 请求,不看 I/O 请求的大小。ioutil 越高表示一直都有 I/O 请求,不代表磁盘无法响应新的 I/O 请求
IOPS:每秒的 I/O 请求数
吞吐量/带宽:每秒的 I/O 请求大小,通常是 MB/s 或者 GB/s 为单位
响应时间:I/O 请求发出到收到响应的时间
饱和度:指的是磁盘处理 I/O 的繁忙程度。这个指标比较玄学,没有直接的数据可以表示,一般是根据平均队列请求长度或者响应时间跟基准测试的结果进行对比来估算
(在做基准测试时,还会分顺序/随机、读/写进行排列组合分别去测 IOPS 和带宽)
上面的指标除了饱和度外,其他都可以在监控系统中看到。Linux 也提供了一些命令来输出不同维度的 I/O 状态:
iostat -d -x :看各个设备的 I/O 状态,数据来源 /proc/diskstats
pidstat -d :看近处的 I/O
iotop :类似 top,按 I/O 大小对进程排序
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70013542/viewspace-2931471/ ,如需转载,请注明出处,否则将追究法律责任。