Linux 文件系统借鉴了inode,inode的结构是
也就是说,在一个分区中 有多少个文件 就有多少个inodes,而一个文件最大,不会超过(12 + 256 + 256 × 256 + 256 × 256 × 256)个数据块大小
同时,目录和普通文件一样,都是一个目录对应一个inode ,如果要打开文件,可以通过文件的inode值在inode数组(inode_table)中找到
就可以得到对应的文件信息
在一个正常的硬盘中 会有MBR + 几个分区 每个子分区的结构为:
(操作系统引导块EBR) + (超级块) + (空闲块位图) + (inode位图) + (inode数组) + (根目录) + (空闲块区域)
占1扇区 1
一个超级块应当包含该硬盘中所有的重要信息 ,其中应该有:
\
mount挂载硬盘原理是:
把硬盘某分区的超级块super_block读到内存中,其中包括 块位图 inode位图信息,从而在对硬盘进行操作时,分区上的超级块也能相应的更新
文件描述符:(同inode区分,可理解为文件数据块描述符,主要用于文件系统对硬盘的管理 而文件描述符主要是和用户相关)
每个文件被打开后,都会自动创建一个文件结构(file 结构),其中记录了文件的偏移量 文件打开的标志 以及对应的inode指针
因为可以由多个进程同时打开一个文件,所以一个文件可能会同时对应多个file结构
文件描述符 int open(const char* pathname, int flags); 返回一个数字 即为文件描述符数组的下标
文件描述符数组元素中的信息又指向某个file结构
到现在成功在文件系统中写入一个inode_no为1 的文件,即除了根目录以后的第一个文件
大概流程:首先是sys_open(char* pathname, uint8_t flags)大概思路为:
1 创建一个路径记录结构 searched_record 用来记录走过的路径
2 调用search_file(char* pathname, &searched_record)检查该目录下是否有同名文件 并返回该文件的inode_no
search_file函数的思想为: 同样借助searched_record结构来记录找过的路径, 每次解析一个路径,并在该级 路径下通过search_dir_entry()函数进行搜索,到最后如果没有搜索到,说明遍历了完整路径
就保存被查找目录的直接父目录并返回最后呢个文件的inode_no
bool search_dir_entry(struct partition* part, struct dir* pdir, const char* name, struct dir_entry* dir_e) 函数 的思想为:首先把该目录下所 有的block读出来 然后一个个遍历
在每个block中保存有很多个目录项 目录项也要逐个便利,并同name比较 若有相同的 就把整个目录项拷贝出来 放在dir_e中 并返回true
3 解析路径深度 ,然后将pathname的路径深度同searched_record搜索过的深度进行比较,不同则中间有目录不存在,相同的话再根据search_file返回的inode编号判断时候找到文件,如果没找到,flags也不是要创建文件,就直接返回-1 如果要求创建文件 就调用file_create(struct due* parent_dir, char* filename,uint8_t flags)创建文件
file_create()函数的思想:
先为新文件分配一个inode 在文件描述符数组中分配一个位置 然后通过create_dir_entry()函数创造一个目录 然后将内存数据同步到硬盘 包括 父目录的inode节点 新创建文件的inode节点 inode的位图 创建文件的open_inodes链表
create_dir_entry()函数的思想:根据filename和inode编号来在内存中对目录进行初始化
文件的打开与关闭:
还是原来的那张图 在每个线程中都会有一个文件描述符数组 (局部)其中存储的应该是文件结构表(全局)的下标 通过访问每个线程的fd_table来获得下标 从而访问到文件结构表 文件结构中包括 fd_pos fd_inode fd_flag 从而通过inode来访问文件
文件打开通过sys_open函数来实现 参数为inode编号 和flag 首先在全局的文件结构表中为文件分配一个空位 然后将文件结构初始化 其中用到了inode_open函数来将inode赋值给文件结构的inode 然后检测是否有write_deny
inode_open 函数:检测open_inodes队列中是否存在该inode 没有的话就去硬盘上 通过inode_locate函数定位inode在硬盘上的位置并读入到open_inodes链表中
inode_locate(struct partition* part, uint32_t inode_no, struct i node_position* inode_pos)函数:判断该inode是否跨过两个扇区 并将inode地址保存到inode_pos中
文件的关闭通过sys_close函数来实现 参数为文件描述符fd 首先通过本地的文件描述符 (即cur_thread的fd_table数组的下标)来获得全局描述符file_table数组中的文件结构 再通过file_close()将其关闭
file_close()参数为文件结构 简单来说就是将write_deny 置为false 并将文件的inode在open_inodes中关闭 并将该文件结构中的inode置为null
同时还要讲线程本地的fd_table中对应的那一位文件描述符置空