【Linux内核】---- 03 安装文件系统
发布日期:2021-06-29 14:51:06 浏览次数:3 分类:技术文章

本文共 2890 字,大约阅读时间需要 9 分钟。

【Linux内核】---- 03 安装文件系统

3.1 从硬盘上获取hello.txt 文件的 i 节点

在文件系统中,每个文件都对应一个唯一的 i 节点。

目录文件和普通文件是有区别的,它们存储的内容不一样。目录文件存储着若干个目录项,每个目录项由两部分组成:

一个是文件名,表明该项目所对应的文件名,它可以是对应着普通文件,也可以对应着目录。
另一个是 i 节点号,表明该目录项所对应的文件在 i 节点表中的项号,通过这个i节点表中找到所对应的文件的 i 节点。

整个解析过程如下

根目录文件 i 节点 ----> 找到根目录文件 ----> mnt目录文件 i 节点 ----> 对应硬盘上超级块
----> 磁盘根目录文件 i 节点----> 找到硬盘根目录文件 ----> user目录文件 i 节点 —> 找到user 目录文件
----> hello.txt文件 i 节点 —> 找到hello.c 文件。
在这里插入图片描述

3.1.1 准备查找枝梢 i 节点 ---- user目录文件的 i 节点

hello.txt 的目录为 /mnt/user/hello.txt

通过路径解析出 i 节点,这是由open_namei函数完成的,所以sys_open 函数接下来要调用open_namei

// fs/open.cint sys_open(const char * filename, int flag, int mode){
if( (i = open_namei(filename, flag, mode, &inode) ) < 0 ) ...}

进入 open_namei 函数后,调用 dir_namei 函数,通过解析路径名得到枝梢 i 节点,对于 “/mnt/user/hello.txt” 这个路径名而言,枝梢i 节点就是 user这个目录文件的 i 节点,执行代码如下:

// fs/namei.cint open_namei(const char * pathname, int flag , int mode, struct m_inode ** res_inode){
if(!(dir = dir_namei(pathname, &namelen, &basename ))) ...}

进入 dir_namei 函数 后,调用 get_dir 函数,同时将路径名也传递下去,开始实质性的 i 节点解析工作。

// fs/namei.cstatic struct m_inode * dir_namei(const char * pathname, int * namelen, const char ** name){
if(!(idr = get_dir(pathname))) ...}

3.1.2 确定查找操作起点

进入 get_dir 函数后,开始对路径名进行分析,

// fs/namei.cstatic struct m_inode * get_dir(const char * pathname ){
if((c = get_fs_byte(pathname)) == '/' ){
inode = current->root; pathname++; }}

3.1.3 获得名为mnt的目录项

  1. 先解析出 mnt 这个字符串的长度。
// 代码路径: fs/namei.cstatic struct m_inode * get_dir(const char * pathname){
for(namelen = 0; (c = get_fs_byte(pathname++)) && (c!='/'); namelen++)}
  1. 再以mnt这个名字为参照,在根目录文件中找到名字为mnt的目录项,
// 代码路径: fs/namei.cstatic struct m_inode * get_dir(const char * pathname){
if(!(bh=find_entry(&inode, thisname, namelen, &de)))}

thisname 标识了mnt字符串的起始位置,namelen标识了该字符串的长度,这样就能锁写mnt这个 字符串。

进入find_entry函数后,开始将根目录文件读取出来,从中找到 名字为mnt的目录项,读取并分析的过程 是这样的:
先确定这个目录文件的大小,因为确定了大小就可以确定目录文件包含多少条目录项,方法是通过根 i 节点中表示根目录文件大小的 i_size 字段除以每个目录占用的字节数。

// fs/namei.cstatic struct buffer_head * find_entry(struct m_inode ** dir, const char * name, int namelen, struct dir_entry ** res_dir){
entries = (*dir)->i_size / (sizeof( struct dir_entry) );}
  1. 从目录文件的第一个数据块开始读取数据,将数据块读入到 缓冲块,并调用match(namelen, name, de) 函数分析这些数据中有没有mnt的目录项。
// fs/namei.cstatic struct buffer_head * find_entry(struct m_inode ** dir , const char *name, int namelen, struct dir_entry ** res_dir){
if(! (bh = bread((*dir)->i_dev, block)) ) de = (struct dir_entry *)bh->b_data; while(i < entries){
if((char *)de >= BLOCK_SIZE + bh->b_data){
breles(bh); bh = NULL; if(! (block = bmap(*dir, i/DIR_ENTRIES_PER_BLOCK)) || !(bh = bread((*dir)->i_dev, block))){
i += DIR_ENTRIES_PER_BLOCK; continue; } de = (struct dir_entry *) bh->b_data; } if(match(namelen, name, de)){
*res_dir = de; return bh; } de++; i++; }}
  1. 最终找到 mnt 这个目录项,值得注意的是,根目录文件在虚拟盘上,所以此时调用bread 函数从设备上读取数据并不会产生中断,之后,find_entry 函数就返回了,

转载地址:https://ciellee.blog.csdn.net/article/details/104837103 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:【Android 输入子系统 01】- 前言
下一篇:【Linux内核】---- 02 从main到怠速

发表评论

最新留言

很好
[***.229.124.182]2024年04月25日 04时56分11秒