【README】

1.本文内容总结自 B站 《操作系统-哈工大李治军老师》,内容非常棒,墙裂推荐;

背景:

  • 磁盘格式化后,其组成部分包括引导块,超级块,inode使用位图,盘块使用位图,inode数组,数据区(如上图所示);

【图解】目录解析步骤:(以解析 /my/data/a文件为例)

  • 步骤1:通过超级块计算出inode数组起始位置,inode数组的第一个inode就是根目录inode(或FCB);
  • 步骤2:通过根目录inode查找子目录项列表(形如 <my,103> <data,203>格式),在目录项列表中查找名称为my的inode编号103;
  • 步骤3:根据目录my的inode编号103到inode数组中读取目录my对应的inode103;
  • 步骤4:通过inode103查找子目录项列表,从中查找名称为 data 的inode编号203;
  • 步骤5:以此类推,找到目录或文件a的inode(如inode303);
  • 步骤6:通过inode303获取文件描述符fd(该文件在PCB数组的下标),把fd和要操作的字符位置送入到 read系统调用(函数)获取文件a的盘块号(如789)(因为文件a的内容分散在多个盘块,需要根据字符位置找到具体某个盘块);
  • 步骤7:把盘块号添加到请求队列;
  • 步骤8:磁盘驱动根据电梯算法获取盘块号,并计算出CHS(柱面号,磁头号,扇区号),通过out命令把参数送入磁盘控制器;
  • 步骤9:磁盘控制器根据CHS操作磁盘进行读写,如读操作,则读入到内存缓冲区(循环读取,每次1个字符);
  • 步骤10:读磁盘操作完成后,磁盘控制器发出中断,中断处理程序唤醒睡眠的用户线程;
  • 步骤11:用户线程把内存缓冲区的数据根据用户程序指令送入cpu进行进一步处理;

补充:目录解析过程也可以参考下图。

上面是解析目录的整个过程,接下来看下目录解析的代码实现;


【1】目录解析的代码实现

具体的,目录解析就是  open(/xx/test.c) 打开文件的具体代码实现;

1)open(...)打开文件

【图解】

  • open_namei是目录解析函数;
  • open_namei 调用了 dir_namei 函数,dir_namei 函数调用了 get_dir(...) 函数;

2)get_dir(...) 函数

【代码】

// 目录解析 /my/data/a
static struct m_inode *get_dir(const char* pathname)
{if ((c=get_fs_byte(pathname)) == '/') {// 1.找到根目录的inodeinode = current->root;pathname++;} else if (c) {inode = current->pwd; }while(1) {if (!c) return inode; // 2.find_entry 从根目录中读取给定路径名my的目录bh = find_entry(&inode, thisname, namelen, &de);// 3.获取该目录my的索引节点 int inr = de->inode; int idev = inode->i_dev; // 4.再读取目录my的下一层inode, inr是目录my的inode下标inode = iget(idev, inr); }
}   

目录解析步骤:

  • 1.找到根目录的inode;
  • 2.find_entry :从根目录中读取给定路径名my的目录;
  • 3.获取该目录my的索引节点 ;
  • 4.iget(idev, inr)函数:再读取目录my的下一层inode, inr是目录my的inode下标;

【2】目录解析-从根目录开始-iget()

iget(dev, inr) 函数的作用是 读取当前 inode 的下一层 inode ;

【图解】
1)setup(): 挂载硬盘;
2)mount_root() :挂载根目录; mount_root函数调用了 iget() 函数具体挂载根目录;

4)iget() 函数读取根目录的代码实现

【图解】
1)get_super() 获取超级块;  
2)引导块+超级块占用2个块号;

block =  2 + sb->s_imap_block + sb->s_zmap_blocks +
(inode->i_num-1)/INODES_PER_BLOCK;
  • s_imap_block  表示i节点位图 ;
  • S_zmap_block 表示 盘块位图;
  • inode->i_num 表示 要操作的目录inode的编号; 如 my的inode下标是13;即i_num是13;

所以相加结果 block 表示的是 查找目录的盘块号(这里没太懂) ;
3)bread(inode->i_dev, block) :

  • 把block送入 bread函数从磁盘读取该盘块号的数据;

【3】 find_entry(...) 找到目录项

1)Find_entry()的作用是:

  • 查找目录项列表,以找到 给定目录my的编号103;my的目录项形如 <my, 103> ;
  • 编号103是FCB(inode)数组的下标;

【图解】
1)找到直接索引块,并读入到内存 ;

int block = (*dir)->i_zone[0] ;  // 查找直接索引块的盘块号
*bh = bread((*dir)->i_dev,block);  // 去磁盘读取该盘块内容

2)从内存缓冲区中把 b_data 取出来 (b_data存储了子目录项列表)

struct dir_entry *de = bh->b_data ;
While(i<entries) {// 遍历子目录项列表查看是否匹配给定路径的目录名
If (match( namelen, name, de )) {
*res_dir = de;
return bh ;
}
de++; i++;
}
  • 一旦匹配完成,则目标目录项就找到了;
  • 目标目录项有了之后,就可以找到对应的inode下标如13;
  • inode下标一旦找到,送入 iget(..) 把inode读出来;
  • 根据要操作者的字符位置和 inode中的盘块索引可以计算出 盘块号;
  • 把盘块号送入 请求队列 ,磁盘驱动程序把盘块号计算出CHS;
  • 把CHS送入磁盘控制器进行磁盘读写;

【图解】

  • block = bmap(*dir, i/DIR_ENTRIES_PER_BLOCK)
  • 循环获取盘块号,或者在一阶间接索引,或者在二阶间接索引;

【小结】目录解析步骤(代码层面)

  • 步骤1: 调用 iget( dev, nr ) 查询给定下标为nr的inode;
  • 步骤2: iget()函数 首先把超级块读入到内存;
  • 步骤3: 把超级块中的 s_imap_blocks 与 s_imap_blocks 相加,再加2,再加 nr 可以得到nr对应的inode的位置;如果nr等于1,则该inode就是根目录inode;
  • 步骤4:把根目录inode读入到内存放入进程的PCB;
  • 步骤5:在进程创建(fork)时,所有进程互相拷贝;这个根目录 inode 在每个进程的PCB都有了;
  • 步骤6:在目录解析时,如果是根目录 ”/” ,则解析根目录inode得到数据块,数据块存储了子目录项列表,形如 <my, 103> <var, 203> ;
  • 步骤7:如路径是 /my/data/a  ; 则通过 子目录项列表查找名称为my的inode下标为 103;
  • 步骤8:根据下标103到inode数组读取目录my的inode,根据字符位置和inode从而可以计算出盘块号  ;
  • 步骤9: 读取盘块号的内容,包括了PCB(inode)数组, 和数据块(存储了下一层子目录项列表);
  • 步骤10:依次类推,可以把 data目录的 inode 读取出来,进而把文件a 的盘块号找到并读入到内存;

【4】操作系统全图

2个视图:

  • 多进程视图(最重要);
  • 文件视图;

28.文件目录解析代码实现相关推荐

  1. 【Groovy】Groovy 脚本调用 ( Groovy 配置文件格式 | Groovy 配置文件读取 | 完整配置文件及解析代码示例 )

    文章目录 前言 一.Groovy 配置文件格式 二.Groovy 配置文件读取 二.完整配置文件及解析代码示例 前言 在 Groovy 脚本 , Groovy 类 , Java 类中 , 可以调用 G ...

  2. 技术解析+代码实战,带你入门华为云政务区块链平台

    摘要:政务区块链平台是行业区块链平台的初步实践,未来在区块链技术的发展下,还会打造面向其他领域的链管平台,构建多方协同的分布式账本,让区块链应用更便捷高效的为产业服务. 本文分享自华为云社区<技 ...

  3. MediaInfo源代码分析 5:JPEG解析代码分析

    ===================================================== MediaInfo源代码分析系列文章列表: MediaInfo源代码分析 1:整体结构 Me ...

  4. html() 无效,Internet Explorer无效HTML解析代码漏洞

    Internet Explorer无效HTML解析代码漏洞 2006-04-13 eNet&Ciweek 受影响系统: Microsoft Internet Explorer 5.0 Micr ...

  5. 支持m3u8的php视频cms,分享一个苹果CMS可用P2P的M3U8解析代码

    苹果CMS可用P2P的M3U8解析代码,非CDNbye的P2P.<?php /** * @代码开源,透明,请勿用于商业用途,完全开源模式,供大家一起探讨研究 * @支持全网(支持跨域)的M3U8 ...

  6. 28行python代码实现哈工大一键申请出校41天

    28行python代码实现哈工大一键申请出校41天 原理 概括:利用平台bug批量构造和发送申请出校请求 哈工大学工平台的出校申请接口主要有两个 获取出校申请列表 import requestsurl ...

  7. 2020年第11届蓝桥杯省赛Python组(真题+解析+代码):数字三角形

    大家好,我是爱分享的小蓝,欢迎交流指正~  1 真题 输入 5 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 输出 27 2 解析 难度系数:⭐⭐ 考察题型:动态规划 涉及知识点:模块 ...

  8. 【C++】JOISC 2020 Day3原题+翻译+解析+代码

    JOISC 2020 Day3 T1 Constellation3 原题 链接 翻译 题目描述 输入格式 输出格式 样例输入 1 样例输出 1 样例解释 1 样例输入 2 样例输出 2 样例解释 2 ...

  9. html文本框怎么写表情,js文本框插入表情支持解析代码

    特效描述:js文本框 插入表情 支持解析代码.js文本框点击选择插入表情,支持代码解析输出. 代码结构 1. 引入CSS 2. 引入JS 3. HTML代码 easyEditor @某某 获取内容Ht ...

最新文章

  1. KVM虚拟化存储管理
  2. VSCode 阅读 Linux 代码怎么才不卡顿?这样做才能快的飞起!
  3. 创新品类,N次方的市场爆炸力
  4. 小米5安卓使用微信X5 Blink内核调试
  5. 亚马逊加入微软Facebook框架联盟,抱团挑战TensorFlow霸权?
  6. JQuery AJAX处理页面返回的XML
  7. 【分享】迅为iTOP4412开发板-Android系统屏幕旋转设置
  8. 浏览器linux2019,2019火狐浏览器
  9. jmeter 调试取样器
  10. Linux苹果工具,Projectsandcastle:一款针对iPhone的AndroidLinux支持工具
  11. Javascript文件加载:LABjs和RequireJS
  12. ROS学习笔记之——MAC安装ubuntu虚拟机
  13. Revel组件化开发框架
  14. 【办公】Gmail的常用方法以及小技巧
  15. “缺钱”的女人,掩饰不住以下三个特征,别不信
  16. 七牛云这个API,让我轻松搞定Banner背景自动切换的功能
  17. FPGA Implementation of BPSK Modulator and Demodulator
  18. 快速实践大规模轻量级图片分类模型:飞桨识图 PP-ShiTu
  19. 自定义Firefox、IE收藏夹
  20. 闲谈swi与ucos

热门文章

  1. 开源移动设备管理(MDM)解决方案的利与弊
  2. 如何用将top命令的结果写入txt?
  3. 将字符串转换成对应的数
  4. [裴礼文数学分析中的典型问题与方法习题参考解答]4.3.21
  5. 什么是人群标签,旺旺号标签如何查询,淘宝号搜索标签查询,淘宝号的千人千面,买家行为标签透视,旺旺号标签API接口
  6. 副业新风口:TikTok(海外抖音)搬运视频,1天1小时!一月3W!(可批量操作)...
  7. win11一开机就显示“无法打开这个应用,查看Microsoft store,了解有关Nahimic的详细信息”怎么解决?
  8. 什么是php 抽象类
  9. 【马司机带带我】电话骚扰自动化及其对策
  10. 2022 IDEA全家桶使用最新主题(免申请)