从0开始的操作系统手搓教程33:挂载我们的文件系统

news2025/3/11 15:35:33

目录

代码实现

添加到初始化上

上电看现象


挂载分区可能是一些朋友不理解的——实际上挂载就是将我们的文件系统封装好了的设备(硬盘啊,SD卡啊,U盘啊等等),挂到我们的默认分区路径下。这样我们就能访问到了(嘿!想象你是一个蚂蚁,别人把葡萄挂到了树枝上,然后你就可以爬着访问到了)

文件系统的挂载和卸载在Linux中是非常重要的功能,它允许用户将一个分区的文件系统与另一个分区的目录树连接起来。通常情况下,Linux会将根分区作为默认分区,并通过mount命令将其他分区挂载到默认分区的某个目录上。在这个过程里,分区的根目录是固定存在的,其他分区尽管有自己的根目录,但它们的根目录并不直接与整个系统的文件结构挂钩。通过mount命令,其他分区可以在需要时被挂载到指定的目录下,而默认分区的根目录则作为所有分区的父目录,挂载后形成一个统一的路径树结构。

对于挂载操作系统到裸盘的情况,并没有现成的分区和文件系统。这时,为了实现文件操作,首先必须在裸盘上创建文件系统,至少要实现基本的文件写入功能。然后,操作系统可以通过文件系统进行安装。例如,在Windows或Linux系统安装过程中,首先会选择目标分区,格式化并安装操作系统到文件系统中。对于学习操作系统实现的场景,虽然也可以模仿这一过程,但为了简化操作,一开始可以避免复杂的分区挂载过程。

实现分区挂载的本质是通过读取硬盘上的元信息并将其加载到内存中,这样,所有硬盘资源的使用情况都能通过内存中的元信息进行管理。当执行写操作时,内存中的数据需要及时同步到硬盘,确保数据的一致性和持久性

代码实现

/* Finds the partition named 'part_name' in the partition list and assigns its 
 * pointer to 'cur_part' */
static bool mount_partition(list_elem *pelem, int arg) {
    // Convert the argument to a partition name string
    char *part_name = (char *)arg;
    
    // Retrieve the DiskPartition structure from the list element
    DiskPartition *part = elem2entry(DiskPartition, part_tag, pelem);
​
    // If the partition name matches, mount this partition
    if (!k_strcmp(part->name, part_name)) {
        cur_part = part; // Set the current partition to the found partition
        Disk *hd = cur_part->my_disk; // Get the disk that contains this partition
​
        // Allocate a buffer to temporarily store the superblock read from disk
        SuperBlock *sb_buf = (SuperBlock *)sys_malloc(SECTOR_SIZE);
​
        // Allocate memory for the superblock of the current partition
        cur_part->sb = (SuperBlock *)sys_malloc(sizeof(SuperBlock));
        if (!cur_part->sb) {
            KERNEL_PANIC_SPIN("alloc memory failed!"); // Kernel panic if allocation fails
        }
​
        // Read the superblock from disk into the buffer
        k_memset(sb_buf, 0, SECTOR_SIZE);
        ide_read(hd, cur_part->start_lba + 1, sb_buf, 1);
​
        // Copy the superblock information from the buffer to the partition's superblock
        k_memcpy(cur_part->sb, sb_buf, sizeof(SuperBlock));
​
        /********** Load the block bitmap from disk into memory **********/
        // Allocate memory for the block bitmap
        cur_part->block_bitmap.bits = (uint8_t *)sys_malloc(sb_buf->block_bitmap_sects * SECTOR_SIZE);
        if (!(cur_part->block_bitmap.bits)) {
            KERNEL_PANIC_SPIN("alloc memory failed!"); // Kernel panic if allocation fails
        }
        // Set the length of the block bitmap in bytes
        cur_part->block_bitmap.btmp_bytes_len = sb_buf->block_bitmap_sects * SECTOR_SIZE;
        
        // Read the block bitmap from disk into memory
        ide_read(hd, sb_buf->block_bitmap_lba, cur_part->block_bitmap.bits, sb_buf->block_bitmap_sects);
        /****************************************************************/
​
        /********** Load the inode bitmap from disk into memory **********/
        // Allocate memory for the inode bitmap
        cur_part->inode_bitmap.bits = (uint8_t *)sys_malloc(sb_buf->inode_bitmap_sects * SECTOR_SIZE);
        if (!(cur_part->inode_bitmap.bits)) {
            KERNEL_PANIC_SPIN("alloc memory failed!"); // Kernel panic if allocation fails
        }
        // Set the length of the inode bitmap in bytes
        cur_part->inode_bitmap.btmp_bytes_len = sb_buf->inode_bitmap_sects * SECTOR_SIZE;
        
        // Read the inode bitmap from disk into memory
        ide_read(hd, sb_buf->inode_bitmap_lba, cur_part->inode_bitmap.bits, sb_buf->inode_bitmap_sects);
        /****************************************************************/
​
        // Initialize the list of open inodes in this partition
        list_init(&cur_part->open_inodes);
        
        verbose_printk("disk mount %s done!\n", part->name); // Print a message indicating successful mounting
​
        // Return true to stop further traversal, as the partition has been found and mounted
        return true;
    }
    return false; // Continue traversing the list if the partition was not found
}
 

mount_filesystem函数就是完成了文件系统中挂载默认分区并加载其元信息的过程。默认分区的名称为 default_part,其值为 sdb1,表示默认操作的分区是 sdb1。分区挂载通过 list_traversal 函数完成,该函数遍历分区列表 partition_list,并对每个分区调用回调函数 mount_partition,传入的参数是 default_part 的地址转换为整型后的值。mount_partitionlist_traversal 的回调函数,其功能是在分区链表中找到与传入的分区名匹配的分区,并将其指针赋值给全局变量 cur_part,用于记录当前操作的分区。

mount_partition 函数中,首先将传入的参数 arg 还原为字符指针 part_name,然后通过宏 elem2entrypelem 还原为分区结构体 part。接着,通过 strcmp 比对 part->namepart_name,如果匹配则找到目标分区,并将其指针赋值给 cur_part。随后,获取该分区所在的硬盘 hd,作为后续硬盘操作的参数。

接下来,系统为超级块申请内存缓冲区 sb_buf,并从硬盘中读取超级块信息到 sb_buf,然后将有用的超级块信息复制到 cur_part->sb 中,忽略填充部分以节省内存。之后,为块位图申请内存,并根据超级块中的 block_bitmap_sects 初始化块位图的大小,最后将硬盘上的块位图读入内存。类似地,系统还会加载 inode 位图到内存中。整个过程确保了分区的元信息被正确加载,并为后续的文件系统操作做好准备。

添加到初始化上

...
    /* Determine the default partition for operations */
    char default_part[8] = "sdb1";
    /* Mount the partition */
    list_traversal(&partition_list, mount_partition, (int)default_part);

上电看现象

下一篇

从0开始的操作系统手搓教程34:说说文件描述符与常见的操作和文件基本操作-CSDN博客文章浏览阅读614次,点赞4次,收藏13次。我们还需要打开根目录并初始化文件表// filesystem_init函数下追加:​​*/return ret;函数将本地文件描述符转换为全局文件表索引。首先,它获取当前任务的文件描述符表,然后根据传入的本地文件描述符返回对应的全局文件描述符索引。sys_close函数用于关闭文件。首先,它检查文件描述符是否大于2(标准输入、输出和错误文件描述符不处理)。然后,调用将本地文件描述符转换为全局文件描述符,并尝试关闭文件。如果成功,更新任务的文件描述符表并返回0;否则,返回-1。 https://blog.csdn.net/charlie114514191/article/details/146143441

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2313281.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于muduo+mysql+jsoncpp的简易HTTPWebServer

一、项目介绍 本项目基于C语言、陈硕老师的muduo网络库、mysql数据库以及jsoncpp,服务器监听两个端口,一个端口用于处理http请求,另一个端口用于处理发送来的json数据。 此项目在实现时,识别出车牌后打包为json数据发送给后端服务…

【Go学习实战】03-2-博客查询及登录

【Go学习实战】03-2-博客查询及登录 读取数据库数据初始化数据库首页真实数据分类查询分类查询测试 文章查询文章查询测试 分类文章列表测试 登录功能登录页面登录接口获取json参数登录失败测试 md5加密jwt工具 登录成功测试 文章详情测试 读取数据库数据 因为我们之前的数据都…

《Python实战进阶》No20: 网络爬虫开发:Scrapy框架详解

No20: 网络爬虫开发:Scrapy框架详解 摘要 本文深入解析Scrapy核心架构,通过中间件链式处理、布隆过滤器增量爬取、Splash动态渲染、分布式指纹策略四大核心技术,结合政府数据爬取与动态API逆向工程实战案例,构建企业级爬虫系统。…

Linux:多线程(单例模式,其他常见的锁,读者写者问题)

目录 单例模式 什么是设计模式 单例模式介绍 饿汉实现方式和懒汉实现方式 其他常见的各种锁 自旋锁 读者写者问题 逻辑过程 接口介绍 单例模式 什么是设计模式 设计模式就是一些大佬在编写代码的过程中,针对一些经典常见场景,给定对应解决方案&…

【氮化镓】高输入功率应力诱导的GaN 在下的退化LNA退化

2019年,中国工程物理研究院电子工程研究所的Tong等人基于实验与第一性原理计算方法,研究了Ka波段GaN低噪声放大器(LNA)在高输入功率应力下的退化机制。实验结果表明,在27 GHz下施加1 W连续波(CW)输入功率应力后,LNA的增益下降约1 dB,噪声系数(NF)增加约0.7 dB。进一…

Javaweb后端文件上传@value注解

文件本地存储磁盘 阿里云oss准备工作 阿里云oss入门程序 要重启一下idea,上面有cmd 阿里云oss案例集成 优化 用spring中的value注解

git规范提交之commitizen conventional-changelog-cli 安装

一、引言 使用规范的提交信息可以让项目更加模块化、易于维护和理解,同时也便于自动化工具(如发布工具或 Changelog 生成器)解析和处理提交记录。 通过编写符合规范的提交消息,可以让团队和协作者更好地理解项目的变更历史和版本…

Java/Kotlin逆向基础与Smali语法精解

1. 法律警示与道德边界 1.1 司法判例深度剖析 案例一:2021年某游戏外挂团伙刑事案 犯罪手法:逆向《王者荣耀》通信协议,修改战斗数据包 技术细节:Hook libil2cpp.so的SendPacket函数 量刑依据:非法经营罪&#xff…

非软件开发项目快速上手:14款管理软件精选

文章介绍了以下14款项目管理系统:1.Worktile;2.Teambition;3.Microsoft Project;4.Forbes;5.WorkOtter;6.Trello;7.Smartsheet;8.Taiga;9.ClickUp;10.Monday.…

夸父工具箱(安卓版) 手机超强工具箱

如今,人们的互联网活动日益频繁,导致手机内存即便频繁清理,也会莫名其妙地迅速填满,许多无用的垃圾信息悄然占据空间。那么,如何有效应对这一难题呢?答案就是今天新推出的这款工具软件,它能从根…

混元图生视频-腾讯混元开源的图生视频模型

混元图生视频是什么 混元图生视频是腾讯混元推出的开源图生视频模型,用户可以通过上传一张图片进行简短描述,让图片动起来生成5秒的短视频。模型支持对口型、动作驱动和背景音效自动生成等功能。模型适用于写实、动漫和CGI等多种角色和场景,…

Debian系统grub新增启动项

参考链接 给grub添加自定义启动项_linux grub定制 启动项名称自定义-CSDN博客 www.cnblogs.com 1. boot里面的grub.cfg 使用vim打开boot里面的grub.cfg sudo vim /boot/grub/grub.cfg 这时候会看到文件最上方的提示 2. 真正配置grub的文件 从刚才看到的文件提示中&#x…

VSCode快捷键整理

VSCode快捷键整理 文章目录 VSCode快捷键整理1-VSCode 常用快捷键1-界面操作2-单词移动3-删除操作4-编程相关5-多光标操作6-文件、符号、函数跳转7-鼠标操作8-自动补全操作9-代码折叠操作 1-VSCode 常用快捷键 1-界面操作 文件资源管理器:Ctrl Shift E 跨文件搜…

刘火良 FreeRTOS内核实现与应用之1——列表学习

重要数据 节点的命名都以_ITEM后缀进行,链表取消了后缀,直接LIST 普通的节点数据类型 /* 节点结构体定义 */ struct xLIST_ITEM { TickType_t xItemValue; /* 辅助值,用于帮助节点做顺序排列 */ struct xLIST_I…

本地部署Navidrome个人云音乐平台随时随地畅听本地音乐文件

文章目录 前言1. 安装Docker2. 创建并启动Navidrome容器3. 公网远程访问本地Navidrome3.1 内网穿透工具安装3.2 创建远程连接公网地址3.3 使用固定公网地址远程访问 前言 今天我要给大家安利一个超酷的私有化音乐神器——Navidrome!它不仅让你随时随地畅享本地音乐…

数据集构建与训练前准备

训练数据集目录结构与格式 作者笨蛋学法,先将其公式化,后面逐步自己进行修改,读者觉得看不懂可以理解成,由结果去推过程,下面的这个yaml文件就是结果,我们去推需要的文件夹(名字可以不固定,但是…

jenkins+ant+jmeter生成的测试报告空白

Jenkins能正常构建成功,但是打开Jenkins上的测试报告,则显示空白 在网上找了很多文章,结果跟别人对比测试报告的配置,发现自己跟别人写的不一样 所以跟着别人改,改成一样的再试试 结果,好家伙&#xff0…

利用阿里云Atlas地区选择器与Plotly.js实现数据可视化与交互

在数据科学与可视化领域,交互式图表和地图应用越来越成为数据分析和展示的重要手段。本文将介绍如何结合阿里云Atlas地区选择器与Plotly.js,创建动态交互式的数据可视化应用。 一、阿里云Atlas地区选择器简介 阿里云Atlas是阿里云的一款数据可视化产品…

linux安装java8 sdk,使用 tar.gz安装包手动安装

1. 下载 Java 8 SDK 首先,需要从 Oracle 的官方网站或 OpenJDK 的网站下载 Java 8 的 .tar.gz 文件。并上传到服务器 2. 解压 JDK 下载完成后,使用 tar 命令解压文件。打开服务器终端,然后使用以下命令: tar -xvzf jdk-8uXXX-…

6.聊天室环境安装 - Ubuntu22.04 - elasticsearch(es)的安装和使用

目录 介绍安装安装kibana安装ES客户端使用 介绍 Elasticsearch, 简称 ES,它是个开源分布式搜索引擎,它的特点有:分布式,零配置,自动发现,索引自动分片,索引副本机制,res…