使用文件系统管理硬件设备
1、描述一个文件系统
介绍如何使用文件系统来管理计算机系统中所有的硬件设计和磁盘
之前直接在sys_open/sys_read/sys_read中对具体的tty设备的打开、读写进行操作,并且只是非常粗浅地介绍了文件系统的一些概念。接下来将正式引入文件系统
由于文件系统需要考虑不同类型的设备、文件的操作,因此文件系统代码必须进行抽象设计
问题:
如何确定当前应用程序操作的是那种类型的文件?
通过灵境前缀来区分,例如/dev/tty0来指定打开tty设备0文件。
针对不同类型的设备、磁盘上的分区中的文件,其操作接口不一致。课程采用的是与设备管理层中类似的方法,即定义一个回调函数表,其中存放与特定类型文件的操作接口
2、挂载设备文件系统
目前仅涉及/dev、/home目录:其中、/dev用于映射到硬件设备的文件系统,如tty。/home目录用于映射到特定的磁盘分区。在访问的时候可以使用类似形如/dev/tty0...类似的形式进行访问
针对不同类似的文件系统,在打开其中的文件时,根据预定的路径前缀进行区分。我们设计了 fs_t结构用于描述某种特定的文件系统。由于文件系统可能会有多种类型的文件系统,因此需要一个初始化列表,将支持的文件系统加入到链表中。后续有关的文件操作,都会先从该表中找到相应的fs_t结构,然后进入到相应的文件系统操作函数中执行
文件系统结构fs_t 中定义了回调函数和指针表
文件系统名称通过挂载点和指定大小保存,类型通过枚举类型定义
文件系统考虑多进程使用,通过指针方式实现互斥锁。
链表管理用于文件系统管理,定义链表节点和目录结构。
设备文件系统代码实现
- 设备文件系统代码实现包括:挂载、读取、写入、关闭等操作函数
- 通过注册回调函数表和设置文件系统类型实现文件系统管理
文件系统初始化与管理
- 定义了mounted list用于存储已初始化的文件系统模块,并设定了系统最多支持十个文件系统节点
- 初始化了空闲列表(free list),将文件系统节点加入其中,以便后续挂载操作
- 实现了mounted list的初始化函数,将空闲列表中的节点添加到mounted list中
- 定义了mount函数,用于挂载文件系统,该函数需要指定文件系统类型、挂载点名称、主设备号和次设备号等参数(在挂载过程中,系统会检查挂载点名称是否已存在,以避免重复挂载。如果挂载成功,将返回文件系统的结构信息。)
- 最后,通过打印信息调试挂载过程,确保文件系统的正确初始化与管理。
文件系统挂载流程解析
- 检查是否有重复项,若无则从空闲列表中分配一个结构,分配成功后,取出对应的文件系统结构并进行初始化,包括设置回调函数表等字段
- 根据文件系统类型获取相应的操作函数指针,并进行设置
- 整个结构进行清零处理,并设置挂载点名称等必要字段
- 调用文件系统操作中的挂载函数进行特定文件系统的初始化操作
2、打开/dev tty0文件
注意的事项为:在打开设备文件系统中的文件时,默认文件名最后的几位为次设备号。
// 打开设备
int dev_id = dev_open(type->dev_type, minor, (void *)0);
if (dev_id < 0) {
log_printf("Open device failed:%s", path);
break;
}
设备文件系统(devfs)包括设备类型、设备名称、文件类型等字段,通过这些字段可以映射到具体的设备驱动程序和设备文件操作
设备文件系统(devfs)通过定义回调函数简化设备文件的读写操作,包括mount、read、write等操作实现
更通用的打开devtty0文件
对sys_open代码进行了优化,使得其打开方式做到更加通用,不再直接使用devfs_open,而是根据路径找到对应的文件系统fs_t结构,再调用其中的open函数,进而使得其代码变得更加通用
对sys_read/sys_write等函数实现做了修改,使其全部采用调用文件系统fs_t中相应的回调函数来完成文件的特定操作,而无需再像以前那样调用设备管理层dev_xxx中的接口。