Qnx 文件系统

QNX Neutrino RTOS提供了丰富的文件系统。与OS中的大多数服务提供过程一样,这些文件系统在内核之外执行;应用程序通过POSIX API的共享库实现生成的消息来使用它们。

如本书所述,这些文件系统中的大多数都是资源管理器。每个文件系统都采用部分路径名空间(称为挂载点),并通过标准POSIX API (open()、close()、read()、write()、lseek()等)提供文件系统服务。文件系统资源管理器接管挂载点并管理它下面的目录结构。它们还检查各个路径名组件的权限和访问授权。

这一执行意味着:
•可以动态启动和停止文件系统。
•多个文件系统可以并发运行。
•无论底层文件系统的配置和数量如何,应用程序都有一个统一的路径名空间和接口。
•在一个节点上运行的文件系统可以从任何其他节点透明地访问。


文件系统和路径名解析

可以无缝地定位和连接到在进程管理中注册的任何服务或文件系统。当文件系统资源管理器注册挂载点时,进程管理器在内部挂载表中为该挂载点及其对应的服务器ID(即, nd, pid, chid标识符)。

这个表有效地将多个文件系统目录连接到用户认为的单个目录中。进程管理器处理路径名的挂载点部分;单独的文件系统资源管理器负责路径名的其余部分。可以注册文件系统(即,安装)以任何顺序。

解析路径名时,进程管理器会联系所有能够处理该路径某个组件的文件系统资源管理器。结果是一组可以解析路径名的文件描述符。

如果路径名表示一个目录,那么在调用readdir()时,进程管理器将询问所有能够解析该目录中文件列表的路径名的文件系统。如果路径名不是目录,则访问解析路径名的第一个文件系统。


文件系统类

可用的许多文件系统可以分为以下几类:

内核:一个特殊的文件系统,它在内核中显示模块,并且总是存在。注意,procnto进程自动提供了一个映像文件系统和一个RAM文件系统。
:在硬盘和CD-ROM驱动器等块设备上运行的传统文件系统。这包括电源安全的文件系统、QNX 4、DOSCD-ROM
闪存:针对闪存设备的特性显式设计的非面向块的文件系统。对于NOR设备,使用FFS3文件系统;对于NAND,使用ETFS文件系统。
网络:提供对远程主机上的文件系统的网络文件访问的文件系统的文件系统。这包括NFSCIFS(SMB)文件系统。
虚拟QNX Neutrino提供了一个虚拟文件系统,一个位于其他文件系统前面的资源管理器,可以解压以前压缩过的文件(使用deflate实用程序)。


文件系统作为共享库

由于在QNX Neutrino RTOS下运行许多文件系统是很常见的,因此它们被设计成一组驱动程序和共享库,以最大化代码重用。这意味着添加额外文件系统的成本通常比其他情况下预期的要小。

一旦初始文件系统开始运行,额外文件系统的增量内存成本就会降到最低,因为只有实现新文件系统协议的代码才会添加到系统中。

20180920173755960.png

如图所示,文件系统和io-blk实现为共享库(本质上是驻留在内存中的被动代码块),而devb-*驱动程序是调用库的执行过程。在操作中,驱动程序进程首先启动然后调用块级共享库(io-blk.so)。稍后可以动态加载文件系统共享库,以提供文件系统接口和服务。

“文件系统”共享库在物理磁盘设备上的一组块上实现文件系统协议。文件系统没有内置到OS内核中;相反,它们是可以根据需要加载或卸载的动态实体。

例如,可以随时插入可移动存储设备(PCCard闪存卡、软盘、可移动盒式磁盘等),并在其中存储许多文件系统。虽然驱动程序接口的硬件不太可能动态更改,但是磁盘上的数据结构可能会有很大的变化。文件系统的动态特性很自然地解决了这个问题


io-blk

大多数文件系统共享库都位于块I/O模块之上。io-blk.so模块还充当资源管理器,并为每个物理设备导出块专用文件。对于有两个硬盘的系统,默认文件是:

/dev/hd0:First hard disk.
/dev/hd1:Second hard disk.

这些文件表示每个原始磁盘,可以使用所有普通的POSIX文件原语(open()、close()、read()、write()、lseek()等)来访问。尽管io-blk模块可以在seek上支持64位偏移,但是驱动程序接口是32位的,允许访问2 tb的磁盘。


Builtin RAM disk

io-blk模块支持通过命令行选项(blk ramdisk=size)创建的内部RAM-disk设备。由于这个RAM磁盘是
io-blk模块内部的(而不是由额外的设备驱动程序(如devb-ram)创建和维护),因此性能明显优于专用的RAM-disk驱动程序。

通过直接在io-blk层合并RAM-disk设备,设备的数据内存与主缓存平行,因此I/O操作可以绕过缓冲区缓存,从而消除内存副本,但仍然保持一致性。与驱动级实现(例如devb-ram)相比,后者透明地将RAM表示为块设备,涉及缓冲缓存中的额外内存副本和重复数据。dll间的标注也被消除。此外,对于拥有硬盘并且需要RAM磁盘的系统,在安装占用方面也有好处:只需要单个驱动程序

Partitions

QNX Neutrino RTOS符合实际的磁盘分区行业标准。

这允许许多文件系统共享相同的物理磁盘。每个分区也表示为块专用文件,分区类型附加到它所在磁盘的文件名。在上面的“双磁盘”示例中,如果第一个磁盘有一个qnx4分区和一个DOS分区,而第二个磁盘只有一个qnx4分区,那么默认文件是:

/dev/hd0:First hard disk

/dev/hd0t6:DOS partition on first hard disk

/dev/hd0t79:QNX 4 partition on first hard disk

/dev/hd1:Second hard disk

/dev/hd1t79: QNX 4 partition on second hard disk

下面的列表显示了一些典型的分配分区类型:


20180920173756556.png
Buffer cache

io-blk共享库实现了所有文件系统都继承的缓冲区缓存。缓冲区缓存试图存储频繁访问的文件系统块,以最小化系统对磁盘执行物理I/O的次数。读操作是同步的;写操作通常是异步的。当应用程序写入文件时,数据进入缓存,文件系统管理器立即响应客户机进程,指示数据已经写入。然后将数据写入磁盘。

关键的文件系统块(如位图块、目录块、区段块和inode块)立即同步写入磁盘。

应用程序可以逐个文件地修改写行为。例如,数据库应用程序可以同步执行给定文件的所有写入操作。这将确保在面对可能导致数据库处于不一致状态的潜在硬件或电源问题时,文件的高度完整性。


文件系统的限制

POSIX定义了文件系统必须提供的一组服务。然而,并不是所有的文件系统都能够提供所有这些服务:


20180920173756511.png
Image filesystem

每个QNX Neutrino系统映像都提供了一个简单的只读文件系统,该文件系统将一组文件内置于操作系统映像中。
由于这个映像可能同时包含可执行文件和数据文件,因此这个文件系统对于许多嵌入式系统来说就足够了。如果需要额外的文件系统,它们将作为模块放置在映像中,以便根据需要启动它们。


RAM filesystem

每个QNX Neutrino系统还提供了一个简单的基于ram的“文件系统”,允许将读写文件放在/dev/shmem下.(注意:/dev/shmem实际上不是一个文件系统。它是一个关于共享内存名称的窗口,这些名称碰巧具有一些文件系统式的特征)。这种RAM文件系统在小型嵌入式系统中最有用,在这些系统中,不需要重新引导进行持久存储,但是需要一个具有有限功能的小型、快速、临时存储文件系统。

文件系统是随procnto免费提供的,不需要任何设置。可以简单地在/dev/shmem下创建文件,并将它们增长到任意大小(取决于RAM资源)。尽管RAM文件系统本身不支持硬链接或软链接或目录,但可以通过使用process-manager链接创建到它的链接。例如,可以创建一个指向基于ram/filedir目录的链接:

2018092017375641.png

这告诉procnto创建一个到/dev/shmem的进程管理器链接,即“/filedir”。然后,应用程序可以打开/filedir下的文件,就好像它是一个普通的文件系统一样。为了最小化进程管理器中RAM文件系统代码的大小,这个文件系统特别不包含“大文件系统”特性,例如文件锁定和目录创建。


嵌入式事务文件系统(ETFS)

ETF实现了一个高可靠性的文件系统,可用于嵌入式固态存储设备,特别是NAND闪存。文件系统支持具有POSIX语义的完全分层目录结构,如上表所示。ETF是一个完全由事务组成的文件系统。每个写操作,无论是用户数据还是文件系统元数据,都包含一个事务。事务要么成功,要么被视为从未发生。

不会重写实时数据。在文件或目录更新中间的写操作总是写到一个新的未使用区域。这样,如果操作部分失败(由于崩溃或电源故障),旧数据仍然完整。

一些基于日志的文件系统也在不会覆盖实时数据的原则下运行。但(ETF)把所有东西都变成了日志记录,把这一点发挥到了极致。文件系统层次结构是通过处理设备中的事务日志动态构建的。这种扫描发生在启动时,但其设计仅读取数据的一小部分并进行crc检查,从而在不牺牲可靠性的情况下加快启动时间。

事务在设备中是位置无关的,可以以任何顺序发生。可以从一个设备读取事务并以不同的顺序将它们写入另一个设备。这很重要,因为它允许对包含可能位于任意位置的坏块的设备进行批量编程。

这种设计非常适合NAND闪存。NAND flash带有工厂标记的坏块,可能在任何位置出现。

20180920173756458.png


1.Inside a transaction 
  每个都包含一个信息头(Header)和一个数据块(data)。信息头中包括:必须属性(与设备无关)
・FID:一个唯一的文件ID,来识别这个transaction。   
・Offset:文件中数据块的偏移。   
・Size:数据块的大小
・Sequence:一个递增的数字,以保证时间顺序   可选属性(与设备相关)
・CRCs:完整性检查数据(支持NAND、NOR、SRAM)   
・ECCs:错误纠正(支持NAND)
・Other:预留位

存储介质类型,虽然etf最适合非和设备,但它也通过以下驱动类支持其他类型的嵌入式存储介质:


20180920173756499.png

尽管etf可以支持NOR flash,但我们推荐使用FFS3 (p.205)文件系统(devf-*),它是为NOR flash设备明确设计的。

2.可靠性
etf的设计是为了在断电时也能生存,即使是在活动的flash写入期间也是如此块擦除。可靠性特性:
•动态损耗均衡
•静态平均读写
•CRC错误检测
•ECC错误纠正
•Read degradation monitoring with automatic refresh
•事务回滚
•原子文件操作
•自动文件碎片整理。


动态损耗均衡:闪存允许在一个闪存块失效前有一定数量的擦除周期。这个数字可能低至10万。ETFS追踪每个区块的擦除次数。在选择使用块时,etf试图将擦除周期均匀地分布在设备上,从而显著提高设备的使用寿命。这种差异可能是极端的, 可能是一个过几天就要坏的快,在ETFS下可能还可以正常使用40年。

静态平均读写:文件系统通常由大量静态文件组成,这些文件可以读,但不能写。这些文件将占用没有被擦除的flash块。如果flash中的大多数文件是静态的,这将导致包含动态数据的其余块以显著增加的擦除损耗。ETFS注意到这些未充分利用的静态块,并通过将它们的数据复制到超负荷使用的块来强制它们投入使用。这解决了两个问题:它让过度损耗的块得到了休息,因为它现在包含静态数据,并且迫使未充分工作的静态块利用起来。

CRC错误检测:每个事务都受到循环冗余检查(CRC)的保护。这确保了对损坏数据的快速检测,在启动时对损坏或不完整事务进行回滚。CRC可以检测出电源故障期间可能发生的多bit错误。

ECC错误纠正:对于CRC错误,ETFS可以应用纠错编码(ECC)来试图恢复数据。这适用于NAND闪存,在正常使用过程中可能出现单比特错误。ECC错误检测到闪存块可能会变弱。etf将为刷新操作标记弱块,刷新操作将数据复制到新的闪存块,并擦除弱块。

Read degradation monitoring with automatic refresh:NAND闪存块中的每次读取操作都会削弱数据bit。大多数设备支持大约100,000次读操作,然后就有丢失的危险。ECC将恢复一个单位错误,但可能无法恢复多位错误。etf通过跟踪读取和在达到100,000读取限制之前标记刷新块来解决这个问题。

事务回滚:ETFS启动时会检查所有事务,并回滚或丢弃损坏和不完全的事务。这种回滚是为了处理电源异常而设计,它也支持多次嵌套的异常。ETFS是根据CRC码来判断买个事务的是否正确的。

原子文件操作:ETFS在设备上实现了一个非常简单的目录结构,它容许在一个flash写操作中作变更。例如,在大多数文件系统中,将文件或目录移动到另一个目录通常是多级操作。在etf中,一个动作是通过一个flash write完成的。

自动文件碎片整理:基于日志的文件系统常常存在碎片问题,因为对现有文件的每次更新或写入都会导致创建新的事务。etf使用写缓冲将小的写合并到大的写事务中,以尽量减少由大量非常小的事务造成的碎片。etf还监控每个文件的碎片级别,并将对严重碎片化的文件进行后台碎片整理操作。请注意,这个后台活动总是会被用户数据请求抢占,以确保立即访问正在整理的文件。

你可能感兴趣的:(Qnx 文件系统)