最近在玩linux嵌入式编程,涉及到文件系统的一些地方不是很懂比如说mount的原理,作为一个有强迫症的人感觉心里痒痒的再加上之前我看过一些内核的书籍有些基础,于是我马上找到相关内核代码跟了一下,且看了一下一些前辈的文章,对linux文件系统大致有了算是比较深入的了解吧。
好了现在进入正题,首先是linux下文件这个概念,文件按理来说就是一堆存储在非易性存储器或者磁盘之类的存储器上的一堆被各种各样格式化的二进制,它是实实在在存储在硬件上的一种“信息”,早期的磁盘上有多个读写磁头,磁头上有线圈,而且有多个带有磁介质的盘面,然后多个磁头做切割磁感线运动产生感应电流(分为读,写磁头),由于磁介质的上的剩磁状态的方向不同,产生的感应电流的方向也不同,两个方向分别代表0,1,于是二进制信息被存储在一层层盘面上,每个盘面被不同半径的圆分成一条条磁道(圆环),而所谓扇区只是磁道上被均分的一部分。以上是文件在硬件介质上大致的存储方式,而在linux里面,为了方便对各种各样的文件各种各样的文件系统(不同的文件系统对存储器上的信息空间的组织和分布不同,如Ext3,FAT32这些)进行管理,采用了VFS(virtual filesystem switch)虚拟文件系统转换这个策略,VFS管理文件是按时管理的,只对已经挂载的文件系统进行管理,linux内核在启动时会自动在根目录下挂载该内核镜像中的文件系统(编译内核时决定),这句话是不是感觉有些绕,举个例子,本来的文件系统是个存储在磁盘的一个文件,该文件包含了对一个储存空间的分布信息(意思是里面分布有一些文件和文件夹)。
其实也就是镜像文件,如图所示,当你不挂载时,VFS不会“展开它”(其实也不知道从哪个目录项展开它,关于目录项之后会讲,现在你就当它是个目录),假设我们要将该文件系统文件挂载到part0,在挂载之前我们先看看当前文件系统下的part0这个目录文件下的信息。
用mount挂载该文件系统文件后(后面我将从内核角度分析这个过程)
你会看到该目录下的信息被改变了,其实key.txt这个文件还在磁盘里面,但是不是在当前这个文件系统的管理下你从当前文件系统就会“看不到了”,你可以umount一下就发现文件又回来了(其实只是那个目录项指向的超级块对象又重新指向之前的文件系统) 其实这些文件名其实是linux内核抽象出来的inode对象里面的一个属性,通通都是对象,你并不是直接对该文件进行操作,而是通过一个结构体指针访问该文件然后进行操作,这些名字只是是存储在内存中的信息,每个“实实在在”的文件linux都有一个inode也叫索引节点对象,每个索引节点对象都有一个索引节点号,内核就是通过这个标识一个文件,而不是文件名,也就是说整个文件的内容和信息被内核隔离开来了,内核通过它给文件标记的信息来管理文件。
VFS下与文件相关的大致有以下对象:
1.文件系统对象在内核里面叫super_block,每个文件系统在挂载时都对应一个超级块对象,一个文件系统可以被多次挂载,可以有多个超级块对象,下面是内核源代码
1349struct super_block {<span style="color:#FF0000;">
1350 struct list_head s_list; /* Keep this first *///内核维持了个超级对象双向链表</span>
1351 dev_t s_dev; /* search index; _not_ kdev_t */设备表示符
1352 unsigned char s_blocksize_bits;//块大小,以位为单位,用过dd命令的就知道文件输入输出一般用块来表示
1353 unsigned long s_blocksize;//块大小,以字节为单位
1354 loff_t s_maxbytes; /* Max file size */
1355 struct file_system_type *s_type;//指向该超级块对象的文件系统类型
1356 const struct super_operations *s_op;//超级块方法
1357 const struct dquot_operations *dq_op;//磁盘限额方法
1358 const struct quotactl_ops *s_qcop;
1359 const struct export_operations *s_export_op;
1360 unsigned long s_flags; //登录标志
1361 unsigned long s_iflags; /* internal SB_I_* flags */
1