3. rawFs文件系统详解

大家好,我是老张。今天我们来聊聊VxWorks里一个比较"原始"但很实用的文件系统——rawFs。说实话,我刚接触VxWorks那会儿,总觉得rawFs这个名字听起来就有点"简陋",后来在项目中真正用上了,才发现它其实是个宝贝。

3.1 rawFs的创建

创建rawFs其实很简单。我习惯用rawFsDevCreate()这个函数。你想想看,它本质上就是在块设备上划出一块区域,然后按扇区来管理。

/* 创建一个rawFs文件系统 */
STATUS rawFsDevCreate
    (
    char *     devName,    /* 设备名称,比如"/rawFs/0" */
    int        blkDev,     /* 块设备描述符 */
    int        startBlk,   /* 起始块号 */
    int        nBlks       /* 块数量 */
    )

嗯,这里要注意几个参数。我在项目中遇到过有人把startBlknBlks搞反了,结果系统直接崩了。说白了,startBlk是起始位置,nBlks是你要占用的块数。

实际案例:我曾经在一个数据采集项目中,用rawFs来管理SD卡上的特定区域。当时的需求是:前1000个扇区留给系统日志,后面2000个扇区存采集数据。代码大概是这样的:

/* 创建两个rawFs分区 */
rawFsDevCreate("/rawFs/log", sdBlkDev, 0, 1000);
rawFsDevCreate("/rawFs/data", sdBlkDev, 1000, 2000);

3.2 rawFs的读写操作

rawFs的读写,说白了就是直接操作扇区。没有目录结构,没有文件名,就是纯粹的块读写。我个人觉得,这种"简单粗暴"的方式在某些场景下反而是优势。

读写操作主要用这两个函数:

/* 打开rawFs设备 */
int fd = open("/rawFs/data", O_RDWR, 0);

/* 读取数据 */
read(fd, buffer, nBytes);

/* 写入数据 */
write(fd, buffer, nBytes);

/* 别忘了关闭 */
close(fd);

我的小技巧:lseek()可以精确定位到某个扇区。比如你要写第50个扇区,可以这样:

lseek(fd, 50 * SECTOR_SIZE, SEEK_SET);
write(fd, data, SECTOR_SIZE);

为什么会推荐这种方式?因为rawFs没有文件分配表,没有目录项,读写就是直接寻址。你想想看,少了这么多中间环节,速度能不快吗?

3.3 rawFs与dosFs的区别

这个问题我经常被问到。咱们直接上对比表:

特性 rawFs dosFs
目录结构 有(树形目录)
文件名 支持长文件名
读写方式 直接扇区读写 通过文件系统层
速度 极快 较慢(有开销)
可靠性 高(无元数据) 中等(有元数据损坏风险)
跨平台 好(FAT格式通用)

我记得有一次,一个同事非要用dosFs来存实时数据流,结果发现写入速度跟不上采样率。我建议他换成rawFs,问题立马解决了。说白了,dosFs虽然功能丰富,但那些目录、文件名、时间戳什么的,在实时数据采集场景下全是累赘。

避坑指南:我曾经遇到过一个问题——用rawFs存数据,突然掉电后,数据居然没丢!这其实是因为rawFs没有复杂的元数据要同步。但反过来,如果你需要文件管理功能,比如删除、重命名、目录浏览,那rawFs就完全帮不上忙了。

3.4 rawFs的应用场景

根据我的经验,rawFs最适合以下几个场景:

  1. 实时数据采集:比如传感器数据、音频流、视频流。不需要文件名,只需要按顺序存。
  2. 系统日志:循环写入日志,覆盖旧数据。用rawFs实现环形缓冲区特别方便。
  3. 启动加载器:Bootloader阶段,文件系统越简单越好,rawFs正合适。
  4. 临时缓存:比如网络数据包的临时存储,用完就丢。

实战经验分享:我在一个无人机飞控项目中,用rawFs来存储飞行参数。每10毫秒记录一次,数据量很大。如果用dosFs,每次写文件都要创建目录项、更新FAT表,开销太大了。换成rawFs后,直接按扇区写,速度提升了3倍多。

嗯,最后总结一下。rawFs虽然"原始",但它的简单、快速、可靠,在某些场景下是无可替代的。我个人建议:如果你的数据不需要文件管理,只需要快速读写,那就大胆用rawFs。但如果你需要跨平台兼容、文件管理功能,那还是老老实实用dosFs吧。

好了,这一章就到这里。下一章我们聊聊dosFs的详细用法,到时候会对比着讲,大家会更清楚什么时候该用哪个。