作者:cyningsun链接:
vfs_caches_init
mnt_init
init_rootfs//注册rootfs文件系统
init_mount_tree//挂载rootfs文件系统
…
rest_init
kernel_thread(kernel_init,NULL,CLONE_FS);就单个文件系统而言,在文件系统安装时,创建超级块对象;沿树查找文件时,总是首先从初识目录的中查找匹配的目录项,以便获取相应的索引节点,然后读取索引节点的目录文件,转化为dentry对象,再检查匹配的目录项,反复执行以上过程,直至找到对应的文件的索引节点,并创建索引节点对象。软链接vs硬链接软链接是一个普通的文件,其中存放的是另外一个文件的路径名。硬链接则指向同一个索引节点,硬链接数记录在索引节点对象的i_nlink字段。当i_nlink字段为零时,说明没有硬链接指向该文件。文件进程管理下图是一个简单示例,说明进程是怎样与文件进行交互。三个不同进程打开同一个文件,每个进程都有自己的文件对象,其中两个进程使用同一个硬链接(每个硬链接对应一个目录对象),两个目录项对象都指向同一个索引节点对象。索引节点的数据又由两部分组成:内存数据和磁盘数据。Linux使用Writeback作为索引节点的数据一致性策略。对于索引节点的数据,当文件被打开时,才会加载索引节点到内存;当不再被进程使用,则从内存踢出;如果中间有更新,则需要把数据写回磁盘。
*"in_use"-validinode,i_count0,i_nlink0*"dirty"-as"in_use"butalsodirty*"unused"-validinode,i_count=0索引节点是否仍在使用,是通过open()和close()操作建立和销毁文件对象,文件对象通过索引节点提供的iget和iput更新索引节点的i_count字段,以完成使用计数。open操作使得i_count加一,close操作使得i_count减一。在close操作时判断索引节点是否释放,如果i_count=0,则意味着不再有进程引用,将会从内存释放。文件磁盘管理
文件与磁盘管理联系最紧密的操作,莫过于touch和rm操作,而尤以后者最为关键。通过strace(或dtruss),查看rm的实际的系统调用
#dtrussrmtmp...geteuid(0x0,0x0,0x0)=00ioctl(0x0,0xA,0x7FFEE06F09C4)=00lstat64("tmp\0",0x7FFEE06F,0x0)=00access("tmp\0",0x2,0x0)=00unlink("tmp\0",0x0,0x0)=00
可以发现rm实际是通过unlink完成的。unlink代表删除目录项,以及减少其索引节点的计数。由通用文件模型可知,父目录本身同样是一个文件,也就意味着目录项是其文件数据的一部分。删除目录项等价于从父目录的文件中删除数据,也就意味着首先要打开父目录的文件。那么,删除操作即可理解为:
删除命令(一个进程)使用open操作获得父目录文件对象
通过iget增加目录文件的索引节点对象计数
读取目录文件数据
将目录文件数据转化为目录项对象
由于目录项包含文件的索引节点,类似的,需要通过iget增加文件的索引节点对象计数
删除目录的目录项
减少文件索引节点对象的硬链接计数i_nlink
通过iput结束对文件索引节点对象的操作,使用计数i_count减一
判断i_count是否为零,如果为零,则释放内存
然后,判断i_nlink是否为零,如果为零,则释放磁盘空间
通过iput结束对目录索引节点对象的操作。
总结回头来看遇到的问题,其实可以从两个角度来理解:
索引与数据文件系统与文件、磁盘管理与文件、进程管理与文件,最核心的都是文件的索引,而不是文件的数据。把数据和索引分开是理解文件系统的关键。缓存策略由于操作系统使用Writeback的策略,意味着只有先释放内存,才有可能释放磁盘。
Whylsof?从上面的模型可以很清楚的理解,因为目录已经没有索引到文件了,但是打开文件还有索引到文件,所以不能立刻释放磁盘空间。为什么lsof可以找到已删除未释放的文件呢?lsof,顾名思义:listopenfiles,该命令的原理就是查找打开文件的列表,因此可以找到已删除未释放的文件。▋书籍推荐
本书汇总了软件工程原则。原则是关于软件工程的基本原理、规则或假设,不管所选的技术、工具或语言是什么,这些原则都有效。
本