跳转至

文件系统开发

文件系统的开发要求

一个文件系统的开发需要考虑多方面的要素,比如:文件系统的类型、大小、性能要求等。如果在嵌入式设备上开发更需要考虑设备的存储容量和处理器速度等因素。大体来说,评价一个文件系统可以参考以下指标: - 可靠性:长时间运行中不出现数据损坏或丢失 - 安全性:保护用户数据不被恶意软件或黑客攻击 - 可扩展性:可以支持更大的存储量和更多的文件 - 兼容性:可以在不同的操作系统和设备上使用 - 性能:文件系统的读写速度与响应时间

基于以上指标,对现有文件系统进行修改或是开发出符合需求的文件系统。

文件系统的开发实际问题

硬件约束

文件系统作为对本地文件进行管理的工具,其安全性、性能等参数必将受限于硬件的性能,在文件系统的开发中硬件的约束不可忽略,但是本项目不涉及硬件的选择,故此不做赘述,以下也不涉及硬件方面的选择。

开发中需要考虑的问题

可靠性

提升文件系统的可靠性的方法主要是两种:避错和容错。其中,避错是指尽量避免出现错误,而容错则是指在出现错误时,能够自动或者半自动地恢复系统。在实际操作中,大多考虑通断电时候文件系统是否仍然可靠。高可靠文件系统的设计原理本质上是copy-on-write,设置transaction point,保证transaction point提交的时候,所有依赖的数据都被正确的写入即可,所以,可靠性的提升实际上是利用硬件空间,且在RTOS上是难以与实时性共存的。

COW(copy-on-write 的简称),是一种计算机设计领域的优化策略,其核心思想是:如果有多个调用者(callers)同时要求相同资源(如内存或磁盘上的数据存储),他们会共同获取相同的指针指向相同的资源,直到某个调用者试图修改资源的内容时,系统才会真正复制一份专用副本(private copy)给该调用者,而其他调用者所见到的最初的资源仍然保持不变。这过程对其他的调用者都是透明的(transparently)。此作法主要的优点是如果调用者没有修改该资源,就不会有副本(private copy)被创建,因此多个调用者只是读取操作时可以共享同一份资源

transaction point是文件系统处于一致状态的时间点。它用于确保数据的完整性和可靠性。设置事务点后,将记录在该点之后对文件系统所做的所有更改。如果文件系统出现问题,可以将其还原到事务点时的状态。这可确保数据不会丢失,并且文件系统保持可靠。

安全性

提升文件系统的安全性需要注意以下几个方面: - 开发语言:开发语言在一定程度上影响了文件系统的安全性,这是由语言自身特性决定的。 - 加密算法:为追求文件系统的安全性也可使用加密算法进行加密。

性能

性能是衡量文件系统读写数据、处理并发请求以及应对不同工作负载的速度和效率的参数,可以说是文件系统优劣的最直观体现。以下是一些进行文件系统性能测试的工具: - Filebench:一个可以生成各种合成工作负载的工具,可以模拟真实的应用服务器场景,比如web服务器、邮件服务器、数据库服务器等,可以使用Filebench测试不同文件系统在不同工作负载下的性能,并比较结果 . - FIO:一个可以使用可配置的工作负载生成器运行各种 I/O 测试的工具。可以使用 FIO 来测试使用不同 I/O 模式、块大小、队列深度等的不同文件系统的性能。 - IOzone:一个可以使用读、写、重读、重写、随机读/写等各种操作来测试文件系统性能的工具。可以使用IOzone来测试不同文件系统的性能使用不同的文件大小、记录长度、线程数等。

开发语言选择问题

本地文件系统或虚拟文件系统的编程语言不必与操作系统相匹配,实际上文件系统只需与VFS的接口进行交互,而虚拟文件系统是物理文件系统实现的抽象,故而仅需注意不同编程语言间的API接口即可。

RTOS的安全问题

RTOS 受到其运行的硬件平台的限制,若对缺少存储器保护的硬件加以保护,其安全级别会受到限制。但存储器和虚拟机可以更高水平的安全性支持引导。诸如 SE Linux、 Green Hills Integrity 和LynuxWorks LynxSecure Embedded Hypervisor 以及 LynxOS-SE RTOS 内的安全策略可比典型 RTOS 提供可靠得多的保护,同时也带来了高成本的问题,所以开发者需进行权衡。

RTOS的性能问题

RTOS最鲜明的特征是实时性,换而言之,是其管理资源 (包括时间和存储器) 的能力。 时序问题与中断响应时间有关,但资源管理时序问题也会同时出现。中断能解决了一系列时序问题,但各应用仍必须利用资源。 考虑存储器分配情况。许多实时应用不采用动态存储器分配,以确保存储器分配和回收时所产生的不同不会变成一个问题。需要动态存储器分配的应用常把存储器划分为 实时和非实时。后者处理动态存储器分配。典型情况下,在使用前,实时部分必须被分 配有足够的存储器。

语言对比

以下对C/C++和Rust的优劣作了对比:

C/C++

C/C++的使用有利于实时性的提升,原因在于其存储器和其它资源的用法显式的,且更接近底层,能直接操作硬件。 但同时,在C/C++开发出来的年代,安全性问题并未得到和性能问题一样的重视导致其很容易出现漏洞,包括但不限于以下 - 释放后使用/双重释放错误:由于需要手动管理内存,导致需要在free时小心翼翼 - 悬空指针:可能导致空指针引用等不安全行为 - 缓冲区溢出错误:这是造成大量漏洞和导致被攻击的原因 - 数据竞争:数据的不安全并发修改 - 未初始化的变量:会引发一系列未定义行为 这也导致了在编写、调试程序时通常需要花费大量的时间来解决内存或数据竞争问题,而人肉 code review 大大降低了效率,也给后续的维护造成了极大的挑战。

Rust

Rust对实时性的支持是不如C/C++的,但是其速度仅仅比C++慢7%

安全性上,Rust 针对内存安全做了严格的限制。 安全地读写内存 - 在限定时间和空间范围内读写内存 - 防止被他人意外修改或释放 - 避免访问空指针和野指针 安全地释放内存 - 在恰当的时机释放 - 确保释放,不遗漏 - 仅释放一次 总体来说 它不允许空指针悬空指针数据竞争。其丰富的类型系统所有权模型保证了内存安全和线程安全,使得能够在编译时消除许多类别的错误。也就是说,一段能跑起来的代码大概率是安全的。

总结

  1. 开发语言的选择不存在理论上的最优选择,但是建议在C、Rust中选择一个。值得指出的是,如果仅仅是VFS采用Rust语言,文件系统的安全性是否能得到较大提升,就目前的知识而言,文件系统的安全性主要还是由其本身决定的。
  2. 开发完VFS后,FreeRTOS的性能等参数仍有待测试。

相关项目

Azure RTOS

Azure RTOS 是一种实时操作系统 (RTOS),适用于由微控制器单元 (MCU) 提供支持的物联网 (IoT) 和边缘设备。 它旨在支持大多数高度受限的设备(电池供电且闪存小于 64 KB)。 Azure RTOS 包括两个主要组件:Azure RTOS ThreadX 和 Azure RTOS GUIX。 Azure RTOS ThreadX 是一种高级实时操作系统 (RTOS),专为深度嵌入式应用程序而设计。 它提供高级调度工具、消息传递、中断管理和消息服务。 Azure RTOS GUIX 是一个专业品质的图形用户界面包,旨在满足嵌入式系统开发人员的需求。 它体积小、速度快,并且可以轻松移植到几乎任何能够支持图形输出的硬件配置。

Azure RTOS FileX

Azure RTOS FileX是一种高性能的文件分配表(FAT)兼容文件系统,与Azure RTOS ThreadX完全集成,并适用于所有支持的处理器。它支持无限数量的介质设备,包括RAM磁盘、FLASH管理器和实际物理设备。它支持12位、16位和32位文件分配表(FAT)格式,并支持扩展文件分配表(exFAT)、连续文件分配,并针对大小和性能进行了高度优化。 Azure RTOS FileX还支持所有Microsoft的文件格式,包括FAT12、FAT16、FAT32和exFAT。 Azure RTOS FileX是Azure RTOS的高级、工业级解决方案,专为深度嵌入式、实时和物联网应用程序而设计。

This is a high-performance, file allocation table (FAT)-compatible file system that’s fully integrated with Azure RTOS ThreadX and available for all supported processors. Like Azure RTOS ThreadX, Azure RTOS FileX is designed to have a small footprint and high performance, making it ideal for today’s deeply embedded applications that require file management operations. FileX supports most physical media, including RAM, Azure RTOS USBX, SD CARD, and NAND/NOR flash memories via Azure RTOS LevelX.

os_filesystem

elliotxx/os_filesystem: A linux-like virtual file system by C++ (github.com) 这是一个仿linux的虚拟文件系统,系统由一个虚拟磁盘文件承载,以文件读写模拟磁盘读写,不涉及底层驱动。

写一个简单的仿linux文件系统,首先需要设计好包含inode、block、superblock、虚拟磁盘布局,空间分配等信息的基本框架。文件系统的开头是一个superblock,包含系统的重要信息,包括inode和block的数量和大小。对于inode,一般来说需要占磁盘空间的百分之一,不过这是个小系统,总大小才5M多一点,所以分配给inode区的空间很少,剩下的空间大部分是block区。