一、inode是什么?
理解inode,要从文件储存说起。
文件储存在硬盘上,硬盘的最小存储单位叫做"扇区"(Sector)。每个扇区储存512字节(相当于0.5KB)。
操作系统读取硬盘的时候,不会一个个扇区地读取,这样效率太低,而是一次性连续读取多个扇区,即一次性读取一个"块"(block)。这种由多个扇区组成的"块",是文件存取的最小单位。"块"的大小,最常见的是4KB,即连续八个 sector组成一个 block。
文件数据都储存在"块"中,那么很显然,我们还必须找到一个地方储存文件的元信息,比如文件的创建者、文件的创建日期、文件的大小等等。这种储存文件元信息的区域就叫做inode,中文译名为"索引节点"。
每一个文件都有对应的inode,里面包含了与该文件有关的一些信息。
二、inode的内容
inode包含文件的元信息,具体来说有以下内容:
* 文件的字节数 * 文件拥有者的User ID * 文件的Group ID * 文件的读、写、执行权限 * 文件的时间戳,共有三个:ctime指inode上一次变动的时间,mtime指文件内容上一次变动的时间,atime指文件上一次打开的时间。 * 链接数,即有多少文件名指向这个inode * 文件数据block的位置
inode结构图:
inode要记录的数据非常多,但偏偏只有128bytes而已,而inode记录一个block号码要花掉4bytes,假设我一个文件有400MB,且每个block为4KB时,那么至少也要10万条block号码的记录。inode哪有那么多可记录的信息?为此,我们的系统聪明的将inode记录block号码的区域定义为12个直接,1个双间接,一个3间接记录区 这样子inode能够指定多少个block呢?我们以较小的1KB的block来说明:
(1) 12个直接指向 12*1K = 12K (2)每条block号码的记录会花去4bytes,因此1K的block大小能够记录256条记录。所以间接地256*1K = 256K (3)双间接 256*256*1K = 256^2K (4)三间接 256*256*256*1K = 256^3K
总额:12+256+256*256+256+256+256=16GB 此时我们知道当文件系统将block格式化为1K大小时,能够容纳的最大文件为16GB,比较一下文件系统的限制表的结果可以发现结果是一致的。但是这个方法不能够用在2K及4K的block大小的计算中,因为2K的block将会受到Ext2文件系统本身的限制,所以计算的结果会有不符合 。
可以用stat命令,查看某个文件的inode信息:
[root@localhost ~]# stat anaconda-ks.cfg File: `anaconda-ks.cfg' Size: 1874 Blocks: 8 IO Block: 4096 regular file Device: fd00h/64768d Inode: 131083 Links: 1 Access: (0600/-rw-------) Uid: ( 0/ root) Gid: ( 0/ root) Access: 2016-12-29 16:35:26.562699425 +0800 Modify: 2016-12-26 15:29:45.735999937 +0800 Change: 2016-12-26 15:29:49.750999936 +0800
总之,除了文件名以外的所有文件信息,都存在inode之中。至于为什么没有文件名,下文会有详细解释。
三、inode的大小
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@localhost ~]# df -i Filesystem Inodes IUsed IFree IUse% Mounted on /dev/mapper/vg0-root 1310720 7556 1303164 1% / tmpfs 125517 1 125516 1% /dev/shm /dev/sda1 51200 38 51162 1% /boot /dev/mapper/vg0-usr 655360 25449 629911 4% /usr /dev/mapper/vg0-var 1310720 1132 1309588 1% /var
查看每个inode节点的大小,可以用如下命令:
[root@localhost ~]# dumpe2fs -h /dev/sda1 | grep 'Inode size' dumpe2fs 1.41.12 (17-May-2010) Inode size: 128
或者 # tune2fs -l /dev/sda7 | grep "Inode size" Inode size: 256
由于每个文件都必须有一个inode,因此有可能发生inode已经用光,但是硬盘还未存满的情况。这时,就无法在硬盘上创建新文件。
四、inode号码
每个inode都有一个号码,操作系统用inode号码来识别不同的文件。
这里值得重复一遍,Unix/Linux系统内部不使用文件名,而使用inode号码来识别文件。对于系统来说,文件名只是inode号码便于识别的别称或者绰号。
表面上,用户通过文件名,打开文件。实际上,系统内部这个过程分成三步:首先,系统找到这个文件名对应的inode号码;其次,通过inode号码,获取inode信息;最后,根据inode信息,找到文件数据所在block,读出数据。
使用ls -i命令,可以看到文件名对应的inode号码:
[root@localhost ~]# ls -i anaconda-ks.cfg 131083 anaconda-ks.cfg
五、目录文件
Unix/Linux系统中,目录(directory)也是一种文件。打开目录,实际上就是打开目录文件。
目录文件的结构非常简单,就是一系列目录项(dirent)的列表。每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。
inode与目录关系图:
ls命令只列出目录文件中的所有文件名:
[root@localhost ~]# ls /var/log anaconda.ifcfg.log anaconda.yum.log cron maillog secure anaconda.log audit dmesg messages spooler anaconda.program.log boot.log dmesg.old ntpstats tallylog anaconda.storage.log btmp dracut.log prelink wtmp anaconda.syslog ConsoleKit lastlog sa yum.log
ls -i命令列出整个目录文件,即文件名和inode号码:
[root@localhost ~]# ls -i /var/log 524312 anaconda.ifcfg.log 524293 ConsoleKit 524305 prelink 524308 anaconda.log 524322 cron 524302 sa 524310 anaconda.program.log 524318 dmesg 524299 secure 524311 anaconda.storage.log 524314 dmesg.old 524301 spooler 524309 anaconda.syslog 524307 dracut.log 524292 tallylog 524313 anaconda.yum.log 524294 lastlog 524295 wtmp 524306 audit 524300 maillog 524342 yum.log 524319 boot.log 524298 messages 524296 btmp 524303 ntpstats
如果要查看文件的详细信息,就必须根据inode号码,访问inode节点,读取信息。ls -l命令列出文件的详细信息。
[root@localhost ~]# ls -l /var/log total 1328 -rw-------. 1 root root 2646 Dec 26 15:29 anaconda.ifcfg.log -rw-------. 1 root root 23138 Dec 26 15:29 anaconda.log -rw-------. 1 root root 45436 Dec 26 15:29 anaconda.program.log -rw-------. 1 root root 113674 Dec 26 15:29 anaconda.storage.log ...
理解了上面这些知识,就能理解目录的权限。目录文件的读权限(r)和写权限(w),都是针对目录文件本身。由于目录文件内只有文件名和inode号码,所以如果只有读权限,只能获取文件名,无法获取其他信息,因为其他信息都储存在inode节点中,而读取inode节点内的信息需要目录文件的执行权限(x)。
六、inode的特殊作用
由于inode号码与文件名分离,这种机制导致了一些Unix/Linux系统特有的现象。
1.有时,文件名包含特殊字符,无法正常删除。这时,直接删除inode节点,就能起到删除文件的作用。
2.打开一个文件以后,系统就以inode号码来识别这个文件,不再考虑文件名。因此,通常来说,系统无法从inode号码得知文件名。
3.cp与inode:分配一个空闲的inode号,在inode表中生成新条目在目录中创建一个目录项,将名称与inode编号关联拷贝数据生成新的文件。
4.rm与inode:链接数递减,从而释放的inode号可以被重用把数据块放空闲列表中删除目录项数据实际上不会马上被删除,但当另一个文件使用数据块时将被覆盖。
5.mv与inode:如果mv命令的目标和源在相同的文件系统,作为mv 命令用新的文件名创建对应新的目录项删除旧目录条目对应的旧的文件名不影响inode表(除时间戳)或磁盘上的数据位置:没有数据被移动!如果目标和源在一个不同的文件系统, mv相当于cp和rm。如果mv命令的目标和源在相同的文件系统,作为mv 命令用新的文件名创建对应新的目录项删除旧目录条目对应的旧的文件名不影响inode表(除时间戳)或磁盘上的数据位置:没有数据被移动!如果目标和源在一个不同的文件系统, mv相当于cp和rm。
注:第3点使得软件更新变得简单,可以在不关闭软件的情况下进行更新,不需要重启。因为系统通过inode号码,识别运行中的文件,不通过文件名。更新的时候,新版文件以同样的文件名,生成一个新的inode,不会影响到运行中的文件。等到下一次运行这个软件的时候,文件名就自动指向新版文件,旧版文件的inode则被回收。