看了很多关于 inode 的资料, 理解 inode 对于理解 Linux 文件系统非常重要, 并对于理解软硬链接及文件存储方式很有帮助, 我结合了网上的资料及我自己学到的知识, 总结了 inode 的一些基本知识, 作为学习的笔记.
文件系统
?? 磁盘存储文件一盘是以扇区为单位, 每个扇区为 512 字节, 操作系统读取硬盘时不是一个一扇区读取, 而是一次读取多个扇区, 多个扇区划分成一个 "块"(block),Linux 以块为单位存储数据, 一般块的大小为 4KB, 也就是 8 个扇区组成一个块.
?? 文件数据都存在块中, 那么关于文件信息存储在哪里, 比如文件权限访问和修改时间等, 我们称为 inode, 就是专门存放文件的元数据信息, 一个分区中如下结构图
?? 第一部分是引导扇区, 负责加载内核; 第二部分是 superblock, 存储 inode/block 的总量, 使用和剩余量及文件系统的信息; 第三部分是 inode, 存储文件的元数据和数据所在的 block 号; 第四部分是 block, 存储文件的数据.
什么是 inode
??inode(index node)是 Linux 和 unix 文件系统的一基本概念, inode 在传统的类 unix 文件系统如 ext3 或 ext4, Linux 扩展文件系统如 ext2 或 ext3 维护这个 inode 数据: inode 表, 每一个 Linux 文件或目录(技术角度本质上没有什么区别), 每个对象在文件系统中用一个 inode 表示, 但什么是对像? 每一个文件在 Linux 中有下列的结构:
文件类型 (可执行, 块设备等)
权限(读, 写, 执行等)
所有者
所有组
文件尺寸
时间戳: 文件访问,(inode)改变和修改时间(记住 Linux 不会记录文件建立时间, 这在 linxu 运维中经常被问的问题)
文件删除时间
链接数量(软链接 / 硬链接)
扩展属性(如 immutable 属性等)
访问控制列表(ACLs)
文件的位置的链接
其它的 matedate 属性
?? 注意 inode 不存文件名字只存内容, 所有以上信息都存在一个 inode 中, 简而言之, inode 就是标识文件或目录属性, 每一个 inode 都有一个唯一的 inode 号, 也称为 index number.
下图为引用网上一张图, Ext2 文件系统的 inode 结构图, 由此计算可得 block 大小为 4k 时的单个文件的最大容量为 4T
?? 下图为文件系统的 block,inode, 目录项的指向情况: 可以看到有两个目录项指向同一个 inode, 链接数会记录在 inode 中, 只有当链接数为 0 时该文件才会被删除, 也就是只有删除所有指向这个 inode 的文件名时才能删除文件
如何检查 inode
如果你想查看 Ext 文件系统中的 inode, 可以使用一些命令查看其属性
显示文件数据信息
你可以使用 stat 显示 inode 数据在一个文件或目录中, 你需要指定文件或目录的名称
- #stat /etc/bashrc
- File: '/etc/bashrc'
- Size: 2853 Blocks: 8 IO Block: 4096 regular file
- Device: 802h/2050d Inode: 3145765 Links: 1
- Access: (0644/-rw-r--r--) Uid: ( 0/ root) Gid: ( 0/ root)
- Context: system_u:object_r:etc_t:s0
- Access: 2019-05-19 15:21:20.360016057 +0800
- Modify: 2018-10-31 03:48:10.000000000 +0800
- Change: 2019-05-16 22:14:01.457994270 +0800
- Birth: -
这个 stat 输出告诉你文件时间戳, 所有者, 权限和存储位置等, 文件的数据存储在磁盘的块中, 在 stat 中都可显示出来.
你可以只显示出 inode number 加 --format 选项输出
- #stat --format=%i /etc/bashrc
- 3145765
显示出文件的 index number
使用 ls 的 - i 选项可以显示出每个文件的 inode number, 可以组合 - l 显示详细信息.
- #ls -il /etc
- total 1324
- 3146085 -rw-r--r--. 1 root root 16 May 16 22:16 adjtime
- 3145764 -rw-r--r--. 1 root root 1518 Jun 7 2013 aliases
- 3148068 -rw-r--r--. 1 root root 12288 May 16 22:17 aliases.db
- 3145741 drwxr-xr-x. 2 root root 4096 May 16 22:14 alternatives
- 3146180 -rw-------. 1 root root 541 Apr 11 2018 anacrontab
- 3145975 -rw-r--r--. 1 root root 55 Oct 30 2018 asound.conf
- 3148004 drwxr-x---. 3 root root 4096 May 16 22:14 audisp
- 3148009 drwxr-x---. 3 root root 4096 May 16 22:17 audit
- 3145794 drwxr-xr-x. 2 root root 4096 May 16 22:14 bash_completion.d
- 3145765 -rw-r--r--. 1 root root 2853 Oct 31 2018 bashrc
- 3146020 drwxr-xr-x. 2 root root 4096 Oct 31 2018 binfmt.d
- 3145851 -rw-r--r--. 1 root root 38 Nov 23 21:16 CentOS-release
第一列显示为 inode number, 你可以显示出各别的文件的 inode number
- #ls -i /etc/bashrc
- 3145765 /etc/bashrc
显示出 inode 空间信息
缺省情况下 df 只会描述磁盘的可用空间, 你可以使用 - i 或 --inodes 选项列出 inodes 的可用空间
- #df -i
- Filesystem Inodes IUsed IFree IUse% Mounted on
- /dev/sda2 3276800 31335 3245465 1% /
- devtmpfs 252061 352 251709 1% /dev
- tmpfs 254731 1 254730 1% /dev/shm
- tmpfs 254731 591 254140 1% /run
- tmpfs 254731 16 254715 1% /sys/fs/cgroup
- /dev/sda1 65536 334 65202 1% /boot
- /dev/sda3 3276800 31 3276769 1% /data
- /dev/sr0 0 0 0 - /mnt/cdrom
- tmpfs 254731 1 254730 1% /run/user/0
这个信息非常有用, 如果你的分区如果有很多非常小的文件, 这会耗尽可用的 inode 空间但磁盘空间没有满.
可以使用 tune2fs -l 命令列出所有关于 inode 的信息
- #tune2fs -l /dev/sda1 | grep inode
- Filesystem features: has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file uninit_bg dir_nlink extra_isize
- Free inodes: 65202
- First inode: 11
- Journal inode: 8
- Journal backup: inode blocks
目录的 inode 结构
?? 如上所述, 目录在 Linux 中也是做一个文件来处理, 目录是一个特别的文件, 他是将文件名映射到 inode number, 也就目录条目或文件, 当我们说目录包含文件或目录时, 也就是说目录映射了这些目录和文件到它们的 inode number, 这也说明为什么一个目录中不能有两个相同的名字, 因为它不能映射一个名子到两个不同的 inode number.
- # ls -ld /data
- drwxr-xr-x. 7 root root 4096 May 18 16:26 /data
当一个文件映射到他的父目录时, 那么它的最顶级目录 (如 / 目录) 如何的呢?/ 目录的 inode number 是固定的, 永远是 2
- #stat /
- File: '/'
- Size: 4096 Blocks: 8 IO Block: 4096 directory
- Device: 802h/2050d Inode: 2 Links: 20
- Access: (0555/dr-xr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
- Context: system_u:object_r:root_t:s0
- Access: 2019-05-19 16:13:40.569926753 +0800
- Modify: 2019-05-16 23:03:45.731938337 +0800
- Change: 2019-05-16 23:03:45.731938337 +0800
- Birth: -
- #stat /boot
- File: '/boot'
- Size: 4096 Blocks: 8 IO Block: 4096 directory
- Device: 801h/2049d Inode: 2 Links: 6
- Access: (0555/dr-xr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
- Context: system_u:object_r:boot_t:s0
- Access: 2019-05-19 15:50:37.520966086 +0800
- Modify: 2019-05-16 22:17:31.300988303 +0800
- Change: 2019-05-16 22:17:31.300988303 +0800
- Birth: -
文件的链接
链接和 index number, 在权限和所有者之间的数字是链接数量, 链接数是指链接到这个文件的硬链接数, 链接分为两种类型, 软链接和硬链接.
软链接(或符号链接)
软链接是一个分开的文件, 他的内容是指向一个链接的文件, 建立一个软链接使用 ln -s, 当使用这个命令时第一个参数为原始文件, 第二个为你想要创建的链接文件.
#ln -s /home/bobbin/sync.sh filesync
文件 filesync 是一个软链接到 sync.sh 文件, 可以想像成一个快捷方式, 便捷 filesync 文件就是编辑原始的文件, 如果你移动或删除了原始文件, 那么 filesync 文件将不会再可用.
使用 ls -l 命令可以显示出文件是软链接文件, 第一个字母为 l 并且有一个指定符>指向原始文件.
- #ls -l filesync
- lrwxrwxrwx 1 root root 20 Apr 7 06:08 filesync -> /home/bobbin/sync.sh
软链接的内容只是目标文件的名称, 你可以看到软链接的权限完全打开的, 因为权限不是它来管理的.
当你比较原始文件和软链接文件, 它们有明显的区别
- #ls -il /home/bobbin/sync.sh filesync
- 258674 lrwxrwxrwx 1 root root 20 Apr 7 06:08 filesync -> /home/bobbin/sync.sh
- 517333 -rw-r----- 1 root root 5 Apr 7 06:09 /home/bobbin/sync.sh
原始文件真接连接到 inode, 但软链接指向它的名字, 软链接文件很小它是参考引用文件名的字节数, 因为没有其它信息可用在软链接文件中.
但注意在软链接建立时如果引用的是相于路径, 那么要参考软链接文件位置的相于路径, 不是参考原始文件的相对路径, 否则你可以使用绝对路径.
列如我有目录:/data/test/test1, 原始文件为 / date/1.sh, 将符号链接建立在 / data/test/test1 目录下, 如果使用如下方法, 产生的软链连将无法使用.
- [[email protected] data]#ln -s 1.sh test/test1/1link
- [[email protected] data]#ll test/test1/1link
- lrwxrwxrwx. 1 root root 4 May 19 17:07 test/test1/1link -> 1.sh (会有红色闪烁表示不可用)
正确的方法是:
- [[email protected] data]#ln -s ../../1.sh test/test1/2link
- [[email protected] data]#ll test/test1/2link
- lrwxrwxrwx. 1 root root 10 May 19 17:11 test/test1/2link -> ../../1.sh
硬链接
重要的理解就是 inode number, 不是名字, 一个硬链接是不同的名称但指向相同的 inode number, 所以当你创建一个新的硬链接就相当于给 inode 增加了一个新的名字而已.
- [[email protected] data]# ls -l 1.sh
- -rwx------. 2 root root 0 May 18 15:53 1.sh
- [[email protected] data]# ln 1.sh test/test1/1hard
- [[email protected] data]# ll test/test1/1hard
- -rwx------. 2 root root 0 May 18 15:53 test/test1/1hard
让我们比较一下这两个文件:
- [[email protected] data]# ll -il 1.sh test/test1/1hard
- 15 -rwx------. 2 root root 0 May 18 15:53 1.sh
- 15 -rwx------. 2 root root 0 May 18 15:53 test/test1/1hard
这两个文件没有什么区别, 除了名字不一样, 你也可以注意到硬链接和软链接不同, 它不是一个特殊的文件, 它们的 inode number 都是 15, 指向了同一个文件, 并且可以看到链接数都为 2, 但硬链接有两个局性:
录不能做为硬链接, Linux 不充许这样维护循环目录树结构
接不能跨文件系统, 也就是说不同的分区, 两个文件必在同一个文件系统, 因为不同的文件系统有不同的独立的 inode 表, 比如相同的 inode number 的两个文件在不同的文件系统上是两个完全不同的文件, 列如我有 / data 和 / boot, 这两个分区文件系统, 如果我建立硬链接时会提示如下:
- [[email protected] data]# ln /boot/vmlinuz-3.10.0-957.el7.x86_64 /data/bootlinux
- ln: failed to create hard link '/data/bootlinux' => '/boot/vmlinuz-3.10.0-957.el7.x86_64': Invalid cross-device link
关于目录的链接数
上面说了, 目录不能做为硬链接, 但同学们有没有注意到, 当你列目录时, 目录的链接数最小是 2, 有的大于 2.
- [[email protected] data]# ll -id /data
- 2 drwxr-xr-x. 8 root root 4096 May 19 18:07 /data
因为在目录创建时本身下会自动创建有一个. 和.. 的代表目录本身和上级目录.
- [[email protected] data]# ls -al /data
- total 2344
- drwxr-xr-x. 8 root root 4096 May 19 18:07 .
- dr-xr-xr-x. 20 root root 4096 May 16 23:03 ..
如何在 Linux 中查找硬链接
你可以检索所有的文件名指向的 inode number, 意思是你可以检索硬链接, 因为它是指向相同内容(inode), 你可以使用 find 带有 - inum 参数
- [[email protected] data]# find / -inum 15
- /sys/fs/selinux/checkreqprot
- /sys/devices/platform/power
- /sys/kernel/debug/boot_params/data
- /data/1.sh
- /data/test/test1/1hard
- /boot/grub/splash.xpm.gz
- /lib64
注意你要分清文件系统, 不是同一个文件系统的文件是完全不同的文件, 虽然 inode number 相同.
Linux 中与 inode 相关的操作
大多数的操作, 如 copy, 执行影响实际链接的文件(但 mv,rm 将会删除或移动软链接本身)
copy 文件
当你 copy 一个文件, 一个新的 inode 也会建立.
- [[email protected] data]# cp test/test1/2link test
- [[email protected] data]# ll -il 1.sh test/2link
- 15 -rwx------. 2 root root 0 May 18 15:53 1.sh
- 917513 -rwx------. 1 root root 0 May 19 17:47 test/2link
2link 是 1.sh 的软链接文件, 可见新的文件建立了自己的 inode number
mv 文件
当移动跨文件系统的文件时, 也就是跨分区时, mv 执行相当于 cp 命令, 只是源文件是被删除的, 但是当移动一个文件在同一个文件系统时, 文件的 inode number 不会改变, 只有目录下的 inode 映射会改变, 实际的数据在硬盘上并没有移动.
- [[email protected] data]# ls -il samlefile.txt
- 18 -rw-r--r--. 1 root root 0 May 19 17:58 samlefile.txt
- [[email protected] data]# mv samlefile.txt test
- [[email protected] data]# ls -il test/samlefile.txt
- 18 -rw-r--r--. 1 root root 0 May 19 17:58 test/samlefile.txt
删除文件
当执行 rm 时, 第一步检查文件的链接数, 如果链接数大于 1, 然后只是删除目录下的一条记录, 并将链接数减 1, 数据仍然存在, inode 也不受影响. 但当链接数为 1 时, 那么 inode 也会被删除, inode number 变为可用, 数据块占用的空间将会被划为可用空间块列表.
- [[email protected] data]# ls -il samplefile.txt samplefile_hardlink.txt
- 21 -rw-r--r--. 2 root root 15 May 19 18:06 samplefile_hardlink.txt
- 21 -rw-r--r--. 2 root root 15 May 19 18:06 samplefile.txt
- [[email protected] data]# rm samplefile_hardlink.txt
- [[email protected] data]# ls -il samplefile.txt
- 21 -rw-r--r--. 1 root root 15 May 19 18:06 samplefile.txt
你可以看到 inode number 减少为 1
结论
每一个 Linux 文件都有一个 inode, 并且 inode 包含文件的所有属性, 但不是文件名称, 软链接是指向原如文件的快捷方式, 硬链接就像一个文件的复本, 原文件和硬链接文件没什么不同, 他们指定相同的 inode.
来源: http://www.bubuko.com/infodetail-3065306.html