个人学习-Linux文件系统架构
1. 参考文章
[1]https://blog.csdn.net/Holy_666/article/details/86532671
[2]CSDN博主土豆西瓜大芝麻:[Linux的VFS详解]:https://blog.csdn.net/jinking01/article/details/90669534
[3]深入理解 Linux的 I/O 系统:https://z.itpub.net/article/detail/9595A9A27188FF73810F07F00DAA08ED
[4]Linux嵌入式的知乎专栏:https://zhuanlan.zhihu.com/p/505338841
[5]博客园博主[李大嘴]:[字符设备和块设备的区别]https://www.cnblogs.com/qlee/archive/2011/07/27/2118406.html
[6]博客园博主[赛艇队长]:[Linux文件系统详述]https://www.cnblogs.com/bellkosmos/p/detail_of_linux_file_system.html
[7]StackExchange:[What are directories, if everything on Linux is a file?]
[8] [The Linux Documentation Project: Filesystem]http://www.tldp.org/LDP/tlk/fs/filesystem.html#tth_sEc9.1.4)
2. 概述:
本文主要从四个角度对Linux文件系统进行总结整理;
-
Linux文件系统的组织方式;
-
Linux的VFS机制和统一文件模型(common file model);
-
Linux系统IO缓冲机制;
3. Linux文件组织方式:
3.1 基础知识:
? 老调重弹:Linux设计的思路,就是一切皆文件,因此Linux中的一切文件都以文件格式保存,而文件根据各自不同的功能分为一下几类:
-
普通文件:
-,常规的文件类型,在Linux中,以.开头的文件为隐藏文件;
-
目录文件;
d, 目录文件,目录文件实际包含两部分Inode和entry(实际所有文件都是这样,不同的是,目录中保存了相关文件的信息);
Linux通过Inode结构体存储目录的基础信息,系统调用stat(),用来访问这个结构和相应信息。
? (图1 源自引用文献[7])
-
字符设备文件;
? c, character device,字符设备是以字符为最小单位进行数据交互的文件,用以驱动字符交互的应用,如键盘(有文章提到oracle是以字符为格式进行数据传输的,记个ToDo);
? 而对于字符设备而言,仅支持顺序访问数据,不支持随机访问。
-
块设备文件;
B,block device driver
? 块设备传输,实际是以固定大小进行数据传输的文件类型,和字符设备不同的是,block支持我们对设备随机访问。最典型的例子即硬盘,操作系统/数据库/其他和磁盘交互应用,实际可以根据自己的规则,去随机访问磁盘的位置,去在该位置写入数据。而通过块设备进行读写时,也需要以bolck为最小单位进行操作(实际上,无论是OS还是DBS,都是以Page去容纳多个Block,然后通过Page进行数据加载,然后以block进行数据解析的)
-
符号链接;(软链接,硬链接实际是生成了一个相应文件,该文件名和原始文件名指向同一个inode):
? 符号链接可以理解成一种快捷方式,允许我们通过符号链接快速访问目标文件。
-
套接字;
S,socket,用于网络通信的文件,通过套接字API形成的一个简单协议族,成对出现进行通信。
-
管道;
? P,进行进程间通信的文件,将一个进程的输出,通过管道,输入到另一个文件。
3.2 文件系统的基本组成
? (Note: 本部分仅介绍基础部分,磁盘分区,初始化,数据在磁盘上的组织后续再进行补充)
? Linux操作系统支持很多不同的文件系统,ext2,ext3,XFS,FAT等等,而Linux把对不同文件系统的访问,交给VFS(virtual file system)来进行。
? Linux的文件系统会为每个文件分配两个数据结构:
? 索引节点(index node) 和 目录项(directory entry),用来记录文件的元信息(meta data)如inode编号,文件大小,访问权限,修改时间,磁盘位置等。索引节点和磁盘上的每个物理文件相对应,而索引节点本身,也存储在磁盘上。
? 目录项(directory entry)用来记录文件的名字,索引节点指针,和其他目录项的层次关系。多个目录项关联起来,就形成了目录结构,和索引节点不同,目录项是由内核维护的数据结构,缓存在内存中;(note:实际上系统启动时,会将相应的数据,加载到树形结构中,维护在内存中)
目录项的结构体,dentry
struct dentry {
atomic_t d_count; /* 目录项引用计数器 */
unsigned int d_flags; /* 目录项标志 */
struct inode * d_inode; /* 与文件名关联的索引节点 */
struct dentry * d_parent; /* 父目录的目录项 */
struct list_head d_hash; /* 目录项形成的哈希表 */
struct list_head d_lru; /*未使用的 LRU 链表 */
struct list_head d_child; /*父目录的子目录项所形成的链表 */
struct list_head d_subdirs; /* 该目录项的子目录所形成的链表*/
struct list_head d_alias; /* 索引节点别名的链表*/
int d_mounted; /* 目录项的安装点 */
struct qstr d_name; /* 目录项名(可快速查找) */
unsigned long d_time; /* 由 d_reva lidate函数使用 */
struct dentry_operations *d_op; /* 目录项的函数集*/
struct super_block * d_sb; /* 目录项树的根 (即文件的超级块)*/
unsigned long d_vfs_flags;
void * d_fsdata; /* 具体文件系统的数据 */
unsigned char d_iname[DNAME_INLINE_LEN]; /* 短文件名 */
};
通过stat访问得到的Inode信息
struct stat { /* when _DARWIN_FEATURE_64_BIT_INODE is NOT defined */
dev_t st_dev; /* device inode resides on */
ino_t st_ino; /* inode's number */
mode_t st_mode; /* inode protection mode */
nlink_t st_nlink; /* number of hard links to the file */
uid_t st_uid; /* user-id of owner */
gid_t st_gid; /* group-id of owner */
dev_t st_rdev; /* device type, for special file inode */
s