2、QNX文件系统基础:层次结构、POSIX兼容性与文件系统类型

好,咱们进入第二章。这一章我打算把QNX文件系统的底子给你讲透。说白了,文件系统就是操作系统和存储设备之间的翻译官。你写的每一个文件,读的每一段数据,都得经过它。我在QNX上折腾了这么多年,踩过的坑有一半都跟文件系统有关。所以这一章,咱们把基础打牢。

2.1 QNX文件系统的层次结构

QNX的文件系统架构,跟Linux不太一样。它走的是微内核路线,文件系统是一个独立的进程,而不是内核的一部分。嗯,这一点很重要。

整个层次结构大致分三层:

  • 应用层:你的应用程序,调用open(), read(), write()这些POSIX接口。
  • 资源管理器层:这是QNX的精华。每个文件系统都是一个资源管理器进程,比如io-blk.so处理块设备,io-nand.so处理NAND Flash。它们通过消息传递与内核通信。
  • 驱动层:最底层的设备驱动,直接跟硬件打交道。

我刚开始接触QNX时,总觉得这架构多此一举。后来在一个车载项目中,文件系统进程崩溃了,你猜怎么着?系统没挂,其他进程照常运行。这就是微内核的好处——隔离性。

关键点:QNX的文件系统不是内核的一部分,而是用户态进程。这意味着你可以动态加载、卸载,甚至替换文件系统,而不需要重启内核。

2.2 POSIX接口兼容性

QNX号称是POSIX兼容的。说实话,它做得比很多Linux发行版都彻底。我见过不少从Linux移植过来的代码,在QNX上几乎不用改。

常用的POSIX接口,QNX都支持:

接口功能QNX支持情况
open()打开文件完全支持
read()/write()读写文件完全支持
lseek()定位文件偏移完全支持
stat()获取文件属性完全支持
mmap()内存映射文件支持,但行为略有差异
ioctl()设备控制完全支持

这里有个坑,我提一下。mmap()在QNX上的行为跟Linux不完全一样。Linux是COW(写时复制)语义,QNX在某些场景下是直接映射。我曾经在一个视频采集项目中,用mmap共享缓冲区,结果在QNX上出现了数据不一致。后来改用消息传递才解决。

我的建议:如果你从Linux移植代码,重点关注mmap()和信号量相关的部分。这两块在QNX上差异最大。

2.3 文件系统类型概览

QNX支持的文件系统类型,比你想象的多。我挑几个常用的说说。

2.3.1 QNX4文件系统

这是QNX自家的老牌文件系统。特点是简单、可靠。用在嵌入式场景很合适。但它不支持日志,掉电容易出问题。我在一个工控项目中吃过这个亏,后来果断换了Power-Safe。

2.3.2 Power-Safe文件系统

这是QNX 6.4之后主推的文件系统。支持日志,掉电恢复能力强。说白了,它就是QNX4的升级版。我现在的项目,只要不是极端资源受限,一律用Power-Safe。

性能数据:Power-Safe在随机写入场景下,比QNX4快约30%。这是我在一个数据采集项目中实测的结果。

2.3.3 闪存文件系统

针对NAND Flash和eMMC优化的文件系统。QNX提供了ETFS(Embedded Transactional File System)。它支持磨损均衡和坏块管理。嗯,这里要注意,ETFS不是通用的,它专门为闪存设计。

我曾经在一个手持设备项目中,直接用Power-Safe挂载eMMC,结果用了半年,eMMC就挂了。后来换成ETFS,加了磨损均衡,设备一直跑到现在都没问题。

2.3.4 网络文件系统

QNX支持NFS和CIFS。这在分布式系统中很有用。我记得有一次调试一个多节点系统,所有节点共享一个NFS存储,调试日志统一写入,排查问题方便多了。

2.3.5 内存文件系统

这个我特别喜欢。QNX提供/dev/shmem和/tmp两种内存文件系统。前者是共享内存,后者是临时文件。速度极快,但掉电数据就没了。适合放临时数据或日志缓冲区。

警告:不要把关键数据放在内存文件系统里。掉电就没了。我曾经见过有人把配置文件放/tmp里,结果一重启系统就起不来了。

2.4 如何选择合适的文件系统

你可能会问,这么多文件系统,我该用哪个?我个人的经验是:

  • 普通存储:Power-Safe,没得说。
  • 闪存设备:ETFS或Power-Safe with wear-leveling。
  • 临时数据:内存文件系统。
  • 网络共享:NFS或CIFS。
  • 极端资源受限:QNX4文件系统,但要做好掉电保护。

嗯,这一章就到这里。下一章我会深入讲Power-Safe文件系统的内部机制,包括日志怎么工作、掉电恢复怎么实现。到时候我会拿一个真实案例来分析。

公众号:蓝海资料掘金营,微信deep3321