索引节点 inode

一言以概之:Linux上一切皆文件,inode则是文件的元信息。Linux分配硬盘空间会包含两部分,一部分是inode区,一部分是data区。

文件储存在硬盘上,硬盘的最小存储单位叫做”扇区”(Sector)。每个扇区储存512字节(相当于0.5KB)。

操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个”块”(block)。这种由多个扇区组成的”块”,是文件存取的最小单位。”块”的大小,最常见的是4KB,即连续八个 sector组成一个 block。

文件数据都储存在”块”中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为”索引节点”。
每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。

可以用stat命令,查看某个文件的inode信息:

root@changcheng:/home/docker# stat docker-compose.yaml 
  File: docker-compose.yaml
  Size: 1874            Blocks: 8          IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 1573431     Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-08-01 05:32:29.455411249 +0000
Modify: 2023-08-01 05:32:12.000000000 +0000
Change: 2023-08-01 05:32:14.870967822 +0000
 Birth: 2023-07-28 05:26:52.057246701 +0000
root@changcheng:/home/docker# file docker-compose.yaml 
docker-compose.yaml: Unicode text, UTF-8 text, with CRLF line terminators

inode也会消耗硬盘空间,所以硬盘格式化的时候,操作系统自动将硬盘分成两个区域。一个是数据区,存放文件数据;另一个是inode区(inode table),存放inode所包含的信息。

每个inode节点的大小,一般是128字节或256字节。inode节点的总数,在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假定在一块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整块硬盘的12.8%。

查看每个硬盘分区的inode总数和已经使用的数量,可以使用df命令。

 ⚡ root@changcheng  ~  df -i                       
Filesystem                         Inodes  IUsed   IFree IUse% Mounted on
tmpfs                             1002117   1106 1001011    1% /run
/dev/mapper/ubuntu--vg-ubuntu--lv 6553600 237044 6316556    4% /
tmpfs                             1002117      1 1002116    1% /dev/shm
tmpfs                             1002117      3 1002114    1% /run/lock
/dev/nvme0n1p2                     131072    310  130762    1% /boot
/dev/nvme0n1p1                          0      0       0     - /boot/efi
tmpfs                             1002117      9 1002108    1% /var/snap/microk8s/common/var/lib/kubelet/pods/cb70e392-313f-4285-b5fb-30107df84b5c/volumes/kubernetes.io~projected/kube-api-access-ll6x4
tmpfs                             1002117      9 1002108    1% /var/snap/microk8s/common/var/lib/kubelet/pods/a91a008a-101a-4448-8dc1-98dddaa9b47d/volumes/kubernetes.io~projected/kube-api-access-v6qzc
shm                               1002117      1 1002116    1% /var/snap/microk8s/common/run/containerd/io.containerd.grpc.v1.cri/sandboxes/a273f929f95b54f78a00c2f1899ca78dc452b56aa0899d8d51101777329325c5/shm
overlay                           6553600 237044 6316556    4% /var/snap/microk8s/common/run/containerd/io.containerd.runtime.v2.task/k8s.io/a273f929f95b54f78a00c2f1899ca78dc452b56aa0899d8d51101777329325c5/rootfs
shm                               1002117      1 1002116    1% /var/snap/microk8s/common/run/containerd/io.containerd.grpc.v1.cri/sandboxes/f7c37d0116b7f6290a1b8763f2c7bb2d94b8e9d9492dcbb079135cd6dc4004dc/shm
overlay                           6553600 237044 6316556    4% /var/snap/microk8s/common/run/containerd/io.containerd.runtime.v2.task/k8s.io/f7c37d0116b7f6290a1b8763f2c7bb2d94b8e9d9492dcbb079135cd6dc4004dc/rootfs
overlay                           6553600 237044 6316556    4% /var/snap/microk8s/common/run/containerd/io.containerd.runtime.v2.task/k8s.io/420b53f8583d0c5b43000267616e31e3eefbc278032caebf4e55ab5418d9a016/rootfs
overlay                           6553600 237044 6316556    4% /var/snap/microk8s/common/run/containerd/io.containerd.runtime.v2.task/k8s.io/de287c4bc83f77bf2d41b867ee605f0643f41b79a3b893034a14308174b9ba05/rootfs
overlay                           6553600 237044 6316556    4% /var/lib/docker/overlay2/58b0100ef141d94b0ade95e1b712374aa2ff439bf55292404c697ba1839103fe/merged
overlay                           6553600 237044 6316556    4% /var/lib/docker/overlay2/454c8ca75abff57d639ac491294abb332c406662bfe98c851ddc04c7027e8733/merged
overlay                           6553600 237044 6316556    4% /var/lib/docker/overlay2/739a34b4240bfe40b96c27b7ddc15ce5f81c5eb53e1dc4dcacc59b09bda23886/merged
tmpfs                              200423     26  200397    1% 

由于每个文件都必须有一个inode,因此有可能发生inode已经用光,但是硬盘还未存满的情况。这时,就无法在硬盘上创建新文件。

inode号码

每个inode都有一个号码,操作系统用inode号码来识别不同的文件。

这里值得重复一遍,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。

表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在的block,读出数据。

使用ls -i命令,可以看到文件名对应的inode号码:

 ⚡ root@changcheng  /home/docker  ls -i docker-compose.yaml 
1573431 docker-compose.yaml

目录文件

Unix/Linux系统中,目录(directory)也是一种文件。打开目录,实际上就是打开目录文件。

目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。

ls命令只列出目录文件中的所有文件名:

 ⚡ root@changcheng  /home/docker  ls -i /etc

1835665 adduser.conf                   1835040 dhcp             1835690 issue.net       1835011 mtab                 1835075 python3.10    1835727 sudo_logsrvd.conf
1835020 alternatives                   1966124 docker           1835050 kernel          1966117 multipath            1835077 rc0.d         1835729 sysctl.conf
1835022 apparmor                       1835041 dpkg             2097156 kubernetes      1835707 multipath.conf       1835078 rc1.d         1835093 sysctl.d
1835021 apparmor.d                     1835675 e2scrub.conf     1835051 landscape       1835708 nanorc               1835079 rc2.d         1835094 systemd
1835023 apport                         1835676 environment      1835053 ldap            1835062 needrestart          1835080 rc3.d         1835095 terminfo
1966081 apt                            1835677 ethertypes       1836050 ld.so.cache     1835709 netconfig            1835081 rc4.d         1836503 thermald
1835666 bash.bashrc                    1966140 fonts            1835692 ld.so.conf      1835063 netplan              1835082 rc5.d         1835730 timezone
1835667 bash_completion                1836550 fstab            1835052 ld.so.conf.d    1835064 network              1835083 rc6.d         1835096 tmpfiles.d
1835025 bash_completion.d              1835678 fuse.conf        1835693 legal           1835065 networkd-dispatcher  1835084 rcS.d         1835097 ubuntu-advantage
1835668 bindresvport.blacklist         1835042 fwupd            1835694 libaudit.conf   1835017 NetworkManager       1835013 resolv.conf   1835731 ucf.conf
1835026 binfmt.d                       1835679 gai.conf         1835054 libblockdev     1835710 networks             1836310 rmt           1835098 udev
1835027 byobu                          1835043 groff            1835055 libnl-3         1835066 newt                 1835718 rpc           1835099 udisks2
1835028 ca-certificates                1836542 group            1835695 locale.alias    1835711 nftables.conf        1835719 rsyslog.conf  1835100 ufw
1836307 ca-certificates.conf           1836522 group-           1836038 locale.gen      1835712 nsswitch.conf        1835085 rsyslog.d     1835101 update-manager
1835669 ca-certificates.conf.dpkg-old  1835044 grub.d           1835744 localtime       1835067 opt                  1835720 screenrc      1835102 update-motd.d
1835029 cloud                          1836533 gshadow          1835056 logcheck        1835012 os-release           1835086 security      1835103 update-notifier
1835030 console-setup                  1835680 gshadow-         1835697 login.defs      1835713 overlayroot.conf     1835087 selinux       1836505 UPower
1966122 containerd                     1835045 gss              1835698 logrotate.conf  1835018 PackageKit           1835721 services      1835732 usb_modeswitch.conf
1835031 cron.d                         1835682 hdparm.conf      1835057 logrotate.d     1835714 pam.conf             1835818 shadow        1835104 usb_modeswitch.d
1835032 cron.daily                     1835683 host.conf        1835699 lsb-release     1835068 pam.d                1835715 shadow-       1835105 vim
1835033 cron.hourly                    1836515 hostname         1835058 lvm             1836611 passwd               1835723 shells        1835106 vmware-tools
1835034 cron.monthly                   1835684 hosts            1835700 machine-id      1836511 passwd-              1835088 skel          1835015 vtrgb
1835670 crontab                        1835686 hosts.allow      1835701 magic           1835069 perl                 1835089 sos           1835733 wgetrc
1835035 cron.weekly                    1835687 hosts.deny       1835702 magic.mime      1835070 pki                  1835090 ssh           1966086 wpa_supplicant
1835036 cryptsetup-initramfs           1966082 ifplugd          1835703 manpath.config  1835071 pm                   1835091 ssl           1835019 X11
1835671 crypttab                       1966125 init             1835059 mdadm           1835072 polkit-1             1836041 subgid        1835734 xattr.conf
1835037 dbus-1                         1835046 init.d           1835704 mime.types      1835073 pollinate            1835725 subgid-       1835107 xdg
1835672 debconf.conf                   1835047 initramfs-tools  1835705 mke2fs.conf     1835716 profile              1836040 subuid        1966130 zsh
1835673 debian_version                 1835688 inputrc          1835016 ModemManager    1835074 profile.d            1836039 subuid-       1835735 zsh_command_not_found
1835038 default                        1835048 iproute2         1835060 modprobe.d      1966127 prometheus           1835726 sudo.conf
1835674 deluser.conf                   1835049 iscsi            1835706 modules         1835717 protocols            1835728 sudoers
1835039 depmod.d                       1835689 issue            1835061 modules-load.d  1835076 python3              1835092 sudoers.d

硬链接

一般情况下,文件名和inode号码是”一一对应”关系,每个inode号码对应一个文件名。但是,Unix/Linux系统允许,多个文件名指向同一个inode号码。

这意味着,可以用不同的文件名访问同样的内容;对文件内容进行修改,会影响到所有文件名;但是,删除一个文件名,不影响另一个文件名的访问。这种情况就被称为”硬链接”(hard link)。

ln命令可以创建硬链接:

ln 源文件 目标文件

例如在对docker-compose创建了硬链接docker-compose-ylj之后,他们两个指向了同一个inode号2753369。删除任何一个都不会影响inode本身及数据本身的变化。

 ⚡ root@changcheng  /usr/local/bin  ln docker-compose docker-compose-ylj
 ⚡ root@changcheng  /usr/local/bin  ls -alFi      
total 114324
2764966 drwxr-xr-x  2 root root     4096 Aug  1 13:06 ./
2752522 drwxr-xr-x  4 root root     4096 Feb 17 17:19 ../
2753369 -rwxr-xr-x  2 root root 54537935 Jul 28 05:21 docker-compose*
2753369 -rwxr-xr-x  2 root root 54537935 Jul 28 05:21 docker-compose-ylj*
 ⚡ root@changcheng  /usr/local/bin  stat docker-compose-ylj
  File: docker-compose-ylj
  Size: 54537935        Blocks: 106528     IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 2753369     Links: 2
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-08-01 01:45:30.714098917 +0000
Modify: 2023-07-28 05:21:03.000000000 +0000
Change: 2023-08-01 13:06:57.927156833 +0000
 Birth: 2023-07-28 05:22:03.657782955 +0000
 ⚡ root@changcheng  /usr/local/bin  stat docker-compose  
  File: docker-compose
  Size: 54537935        Blocks: 106528     IO Block: 4096   regular file
Device: fd00h/64768d    Inode: 2753369     Links: 2
Access: (0755/-rwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2023-08-01 01:45:30.714098917 +0000
Modify: 2023-07-28 05:21:03.000000000 +0000
Change: 2023-08-01 13:06:57.927156833 +0000
 Birth: 2023-07-28 05:22:03.657782955 +0000

软链接

软链接(也称符号链接)可以看成是一个普通的文件,**只不过这个文件中的数据块存放的是源文件的索引节点号。**可以通过为ln指令添加-s(s: soft 的意思)选项创建软链接:

我们在同一目录下创建了docker-compose的软链接和硬链接。

可以看到软链接docker-compose-rlj文件本身只有14个字节,并且指向一个新的inode。硬链接和本身都是53M的大小,但指向同一个inode。

 ⚡ root@changcheng  /usr/local/bin  ls -alFih                       
total 112M
2764966 drwxr-xr-x  2 root root 4.0K Aug  1 13:15 ./
2752522 drwxr-xr-x 10 root root 4.0K Feb 17 17:19 ../
2753369 -rwxr-xr-x  2 root root  53M Jul 28 05:21 docker-compose*
2752681 lrwxrwxrwx  1 root root   14 Aug  1 13:15 docker-compose-rlj -> docker-compose*
2753369 -rwxr-xr-x  2 root root  53M Jul 28 05:21 docker-compose-ylj*
2790458 -rwxr-xr-x  1 root root 1.2M Jul 25 05:43 redis-benchmark*
2790461 lrwxrwxrwx  1 root root   12 Jul 25 05:43 redis-check-aof -> redis-server*
2790460 lrwxrwxrwx  1 root root   12 Jul 25 05:43 redis-check-rdb -> redis-server*
2790459 -rwxr-xr-x  1 root root 1.1M Jul 25 05:43 redis-cli*
2790462 lrwxrwxrwx  1 root root   12 Jul 25 05:43 redis-sentinel -> redis-server*
2790457 -rwxr-xr-x  1 root root 5.5M Jul 25 05:43 redis-server*

显然软链接和文件本身家一个文件。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TWkzLSzz-1690992559057)(assets/image-20230801212613-6s6zd6d.png)]

软链接文件的数据块中仅仅存放着源文件的索引节点号,这也是为什么源文件为 36 个字节,而软链接文件却有 9 个字节的原因。由于软链接只不过是数据块中存放了源文件的索引节点号,因此删除软链接文件并不会影响源文件。但是如果删除源文件,由于软链接文件中指向的索引节点号对应的文件没有了,所以会导致软链接文件失效。

软链接不同于硬链接,在软链接中删除源文件会影响到软链接的使用,因此在 Linux 中会有很多地方标识文件是否为软链接:

  • ls -l指令输出的文件,其中十个字符中的第一个字符代表文件类型,如果文件为软链接文件则为l
  • Linux 会使用特殊的颜色将软链接文件与其它文件进行区分,如果删除了源文件,软链接失效则软链接文件也会呈现失效的颜色;
    在这里插入图片描述

注意:如果软链接文件和源文件不在同一个目录,源文件要使用绝对路径,不能使用相对路径。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值