首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

理解 Linux 的硬链接与软链接(3)

理解 Linux 的硬链接与软链接(3)

链接相关命令在 Linux 中查看当前系统已挂着的文件系统类型,除上述使用的命令 df,还可使用命令 mount 或查看文件 /proc/mounts。
1
2
3
4
5
6
7
# mount
/dev/sda7 on / type ext4 (rw,errors=remount-ro)
proc on /proc type proc (rw,noexec,nosuid,nodev)
sysfs on /sys type sysfs (rw,noexec,nosuid,nodev)
...
...
none on /run/shm type tmpfs (rw,nosuid,nodev)




命令 ls 或 stat 可帮助我们区分软链接与其他文件并查看文件 inode 号,但较好的方式还是使用 find 命令,其不仅可查找某文件的软链接,还可以用于查找相同 inode 的所有硬链接。(见清单 8.)
清单 8. 使用命令 find 查找软链接与硬链接
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 查找在路径 /home 下的文件 data.txt 的软链接
# find /home -lname data.txt
/home/harris/debug/test2/a

// 查看路径 /home 有相同 inode 的所有硬链接
# find /home -samefile /home/harris/debug/test3/old.file
/home/harris/debug/test3/hard.link
/home/harris/debug/test3/old.file

# find /home -inum 660650
/home/harris/debug/test3/hard.link
/home/harris/debug/test3/old.file

// 列出路径 /home/harris/debug/ 下的所有软链接文件
# find /home/harris/debug/ -type l -ls
656662 0 lrwxrwxrwx 1 harris harris 1 Sep 1 14:37 /home/harris/debug/test2/b -> a
656627 0 lrwxrwxrwx 1 harris harris 8 Sep 1 14:37 /home/harris/debug/test2/a ->
data.txt
789467 0 lrwxrwxrwx 1 root root 8 Sep 1 18:00 /home/harris/debug/test/soft.link ->
old.file
789496    0 lrwxrwxrwx   1 root     root            7 Sep  1 18:01
/home/harris/debug/test/soft.link.dir -> old.dir




系统根据磁盘的大小默认设定了 inode 的值(见清单 9.),如若必要,可在格式文件系统前对该值进行修改。如键入命令 mkfs -t ext4 -I 512/dev/sda4,将使磁盘设备 /dev/sda4 格式成 inode 大小是 512 字节的 ext4 文件系统。
清单 9. 查看系统的 inode 值
1
2
3
4
5
6
7
// 查看磁盘分区 /dev/sda7 上的 inode 值
# dumpe2fs -h /dev/sda7 | grep "Inode size"
dumpe2fs 1.42 (29-Nov-2011)
Inode size:              256

# tune2fs -l /dev/sda7 | grep "Inode size"
Inode size:              256




Linux VFSLinux 有着极其丰富的文件系统,大体上可分如下几类:
  • 网络文件系统,如 nfs、cifs 等;
  • 磁盘文件系统,如 ext4、ext3 等;
  • 特殊文件系统,如 proc、sysfs、ramfs、tmpfs 等。
实现以上这些文件系统并在 Linux 下共存的基础就是 Linux VFS(Virtual File System 又称 Virtual Filesystem Switch),即虚拟文件系统。VFS 作为一个通用的文件系统,抽象了文件系统的四个基本概念:文件、目录项 (dentry)、索引节点 (inode) 及挂载点,其在内核中为用户空间层的文件系统提供了相关的接口(见 所示 VFS 在 Linux 系统的架构)。VFS 实现了 open()、read() 等系统调并使得 cp 等用户空间程序可跨文件系统。VFS 真正实现了上述内容中:在 Linux 中除进程之外一切皆是文件。
图 3. VFS 在系统中的架构Linux VFS 存在四个基本对象:超级块对象 (superblock object)、索引节点对象 (inode object)、目录项对象 (dentry object) 及文件对象 (file object)。超级块对象代表一个已安装的文件系统;索引节点对象代表一个文件;目录项对象代表一个目录项,如设备文件 event5 在路径 /dev/input/event5 中,其存在四个目录项对象:/ 、dev/ 、input/ 及 event5。文件对象代表由进程打开的文件。这四个对象与进程及磁盘文件间的关系如图 4. 所示,其中 d_inode 即为硬链接。为文件路径的快速解析,Linux VFS 设计了目录项缓存(Directory Entry Cache,即 dcache)。
图 4. VFS 的对象之间的处理Linux 文件系统中的 inode在 Linux 中,索引节点结构存在于系统内存及磁盘,其可区分成 VFS inode 与实际文件系统的 inode。VFS inode 作为实际文件系统中 inode 的抽象,定义了结构体 inode 与其相关的操作 inode_operations(见内核源码 include/linux/fs.h)。
清单 10. VFS 中的 inode 与 inode_operations 结构体
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct inode {
   ...
   const struct inode_operations   *i_op; // 索引节点操作
   unsigned long           i_ino;      // 索引节点号
   atomic_t                i_count;    // 引用计数器
   unsigned int            i_nlink;    // 硬链接数目
   ...
}

struct inode_operations {
   ...
   int (*create) (struct inode *,struct dentry *,int, struct nameidata *);
   int (*link) (struct dentry *,struct inode *,struct dentry *);
   int (*unlink) (struct inode *,struct dentry *);
   int (*symlink) (struct inode *,struct dentry *,const char *);
   int (*mkdir) (struct inode *,struct dentry *,int);
   int (*rmdir) (struct inode *,struct dentry *);
   ...
}




如清单 10. 所见,每个文件存在两个计数器:i_count 与 i_nlink,即引用计数与硬链接计数。结构体 inode 中的 i_count 用于跟踪文件被访问的数量,而 i_nlink 则是上述使用 ls -l 等命令查看到的文件硬链接数。或者说 i_count 跟踪文件在内存中的情况,而 i_nlink 则是磁盘计数器。当文件被删除时,则 i_nlink 先被设置成 0。文件的这两个计数器使得 Linux 系统升级或程序更新变的容易。系统或程序可在不关闭的情况下(即文件 i_count 不为 0),将新文件以同样的文件名进行替换,新文件有自己的 inode 及 data block,旧文件会在相关进程关闭后被完整的删除。
清单 11. 文件系统 ext4 中的 inode
1
2
3
4
5
6
7
8
9
10
struct ext4_inode {
   ...
   __le32  i_atime;        // 文件内容最后一次访问时间
   __le32  i_ctime;        // inode 修改时间
   __le32  i_mtime;        // 文件内容最后一次修改时间
   __le16  i_links_count;  // 硬链接计数
   __le32  i_blocks_lo;    // Block 计数
   __le32  i_block[EXT4_N_BLOCKS];  // 指向具体的 block
   ...
};




清单 11. 展示的是文件系统 ext4 中对 inode 的定义(见内核源码 fs/ext4/ext4.h)。其中三个时间的定义可对应与命令 stat 中查看到三个时间。i_links_count 不仅用于文件的硬链接计数,也用于目录的子目录数跟踪(目录并不显示硬链接数,命令 ls -ld 查看到的是子目录数)。由于文件系统 ext3 对 i_links_count 有限制,其最大数为:32000(该限制在 ext4 中被取消)。尝试在 ext3 文件系统上验证目录子目录及普通文件硬链接最大数可见 . 的错误信息。因此实际文件系统的 inode 之间及与 VFS inode 相较是有差异的。
清单 12. 文件系统 ext3 中 i_links_count 的限制
1
2
3
4
5
# ./dirtest.sh
mkdir: cannot create directory `dir_31999': Too many links

# ./linkcount.sh
ln: failed to create hard link to `old.file': Too many links




结束语本文最初描述了 Linux 系统中文件与目录被引入的原因及 Linux 处理文件的方式,然后我们通过区分硬链接与软链接的不同,了解 Linux 中的索引节点的相关知识,并以此引出了 inode 的结构体。索引节点结构体存在在于 Linux VFS 以及实际文件系统中,VFS 作为通用文件模型是 Linux 中“一切皆是文件”实现的基础。文章并未深入 Linux VFS,也没涉及实际文件系统的实现,文章只是从 inode 了解 Linux 的文件系统的相关内容。若想深入文件系统的内容,查看内核文档 Documentation/filesystems/ 是一个不错的方式。
返回列表