
在Linux工程项目进行测试时要储存重要的过程文件而文件又有可能过大时可以将文件存在某些闲置分区中例如某些容量比较大的备份分区。要注意的是本次工程实践的硬盘设备是NAND Flash闪存设备。查看分区运行cat /prop/mtd输出当前系统挂载的分区资源各列的含义依次为MTD 设备的编号标识符数字从 0 开始递增表示系统的物理闪存分区序号。分区大小单位字节通常以十六进制表示。擦除块大小单位字节即闪存的最小可擦除单元。分区的名称标签用于标识该 MTD 分区的用途如引导程序、内核、文件系统等。从中挑选合适的分区进行擦除文件系统初始化以及重新挂载。擦除分区挑选合适的分区后需要先将分区中原先的内容擦除可以运行flash_erase [选项] 设备节点 起始块偏移 擦除块数量例如flash_erase /dev/mtdblock0 5 12从第5块开始连续擦除12个块。如果没有集成flash管理工具也可以尝试使用内核级操作# 通过 MTD 字符设备直接操作dd if/dev/zero of/dev/mtdblock0 bs4096 count12 skip5dd指令是非常强大的数据操作指令块级操作dd操作的是数据块Blocks而非文件系统理解的单个文件。它能直接读取和写入磁介质扇区或文件内容因此可以用于处理原始设备如/dev/sda和普通文件。精确控制它对数据传输的来源(if)、去向(of)、块大小(bs)、块数量(count) 等都提供了非常精细的控制。文件名即一切它不关心文件的内容格式、类型它只负责忠实地拷贝字节。dd if输入文件 of输出文件 [选项]if输入文件(input file)。这是数据读取的来源。可以是普通文件如file.iso、物理磁盘设备如/dev/sda、分区如/dev/sda1甚至是标准输入stdin用if/dev/stdin或直接省略if但提供输入源。of输出文件(output file)。这是数据写入的目标。同样可以是普通文件、设备、分区或标准输出stdout用of/dev/stdout或省略of但提供输出目标。选项大小写敏感控制数据传输方式常见的包括关键选项详解bsBYTES块大小(blocksize)。定义一次读取和写入操作的字节数。使用较大的块如bs4M通常性能更好但使用较小的块如bs512可用于特定的精确操作。countBLOCKS要复制的块数量。仅拷贝指定数量的bs大小的块。如果不指定count和skipdd会一直读到输入文件的结束。skipBLOCKS在输入文件中跳过的块数量。在开始读取数据之前先跳过if文件开头的skip个bs大小的区域。常用于恢复备份中的特定分区。seekBLOCKS在输出文件中跳过的块数量。在开始写入数据之前先跳过of文件开头的seek个bs大小的区域从这里开始写入。用于将数据写入到目标设备的特定位置。statusLEVEL状态报告级别。控制传输进度信息statusprogress (GNU dd 特有)定期显示当前速度和传输完成的字节数。statusnone完全不输出状态信息。默认为statusnoxfer只显示统计摘要拷贝了多少字节、共用时间等。convCONVS转换选项(conversions)。这是一个强大的功能可以指定逗号分隔的参数列表notrunc不要截断输出文件。仅修改目标文件的部分内容时保持目标文件中未被修改区域内容的完整即使目标文件原本比你写入的数据量更大。这在使用dd修改磁盘分区上的单个文件内容时非常重要。sparse尝试检测输入块中的大量零字节并将其在输出文件中写成“稀疏文件”占用磁盘块较少。节省空间。noerror读取错误后继续处理而非终止。错误会被报告读取失败的块将被输出填充为全零假设未进行其他转换。sync用 NUL 字节填充每个输入块至ibs大小如果使用了非同obs的选项。这会影响bs,ibs,obs。常与noerror连用。ibsBYTES,obsBYTES输入块大小(input blocksize),输出块大小(output blocksize)。允许输入和输出块大小不同bs同时设置二者。当使用了convsync时输入块将被填充或截断至ibs。初始化文件系统由于存储设备是NADN Flash该分区又是作为日志保存分区有较高频率读写的需求因此需要把分区初始化为UBI(Unsorted Block Images) 分区进行块管理可以使用如下指令ubiformat /dev/device [options]-y强制执行操作跳过确认提示-s size指定擦除块大小单位字节-O size设置子页面大小针对 NAND 闪存优化-e count保留指定数量的擦除块作为备用区-f image从外部文件加载 UBI 镜像例如ubiformat /dev/mtd49值得注意的是每一次进行ubiformat系统会擦除该分区对于NAND设备而言基于寿命的考虑为了不产生更多的坏块应该避免频繁做这样的操作。然后把UBI设备挂载到内核到此系统会在/dev/下创建相应的ubi设备之后即可通过/dev/ubi*对该设备进行操作运行如下指令ubiattach -m MTD设备号 -d UBI设备号 [其他选项]-m MTD设备号指定要附加的 MTD 设备编号如 /dev/mtdX 中的 X。-d UBI设备号指定分配给 UBI 设备的编号如 0 对应 /dev/ubi0。-p MTD分区路径直接指定 MTD 分区路径如 /dev/mtd1替代 -m。-O vid_hdr_offset指定 VID 头偏移量适用于非标准闪存布局。-b max-beb-per1024: 预留一定数量的块给未来可能损坏的块。例如ubiattach -m /dev/mtd49 -d 15 -b 2Attach成功之后可以使用ubinfo查看ubi分区的信息ubinfo device_num例如~ # ubinfo -d 15ubi15Volumes count: 0Logical eraseblock size: 253952 bytes, 248.0 KiBTotal amount of logical eraseblocks: 80 (20316160 bytes, 19.3 MiB)Amount of available logical eraseblocks: 68 (17268736 bytes, 16.4 MiB)Maximum count of volumes 128Count of bad physical eraseblocks: 0Count of reserved physical eraseblocks: 8Current maximum erase counter value: 0Minimum input/output unit size: 4096 bytesCharacter device major/minor: 490:0其中需要关注实际可用的空间大小Amount of available logical eraseblocks。挂载分区到文件夹在UBI分区初始化之后还需要把分区划分成卷才可以挂载到文件夹上这是因为UBI分区并不是一个逻辑分区本质上UBI分区一个eraseblock的池子划分卷可用如下指令ubimkvol [选项] UBI设备节点-n, --vol_idID指定要创建的卷的 ID 号。这是一个整数 如-n 0。-s, --vol_sizeSIZE | max指定卷的大小。可以使用字节单位后缀如2048KiB,512MiB。使用-s max强烈推荐的方式表示使用 UBI 设备上所有剩余的可用空间来创建该卷。-N, --vol_nameNAME为卷设置一个可读的名称字符串。该名称在 UBI 卷操作和格式化时非常有用可以帮助识别。非常重要这对于后续格式化和挂载很有用-t, --vol_typedynamic|static指定卷的类型dynamic: 这是最常见和最推荐的类型。用于可变大小数据如文件系统。static: 仅供存放固定大小的原始数据块如 bootloader 镜像。使用较少。例如ubimkvol /dev/ubi15 -N factory -s 16Mib这里将之前创建的UBI分区划分为一个卷0大小为之前使用的ubinfo中所示可用空间。然后就可以进行文件夹的挂载了这里可以使用mount指令如mount -t ubifs /dev/ubi15_0 /tmp/log当然前提是文件夹存在可以先用mkdir创建文件夹mkdir /tmp/log