这其实已经是在完成了 Hi3531D 的大部分软件开发任务后的复盘笔记。中途都是照着文档说明草草地学、草草地用,跳过了很多很多细节和原理性的东西。嵌入式 Linux 这个知识体系还是有亿点大的,想一口吃成胖子很难,但是其余的不说,基本的了解还是该有的。
仅对接触过的知识点进行复盘和整理,实际上还有非常多的知识是在 Hi3531D 的项目中没有涉及到的,蛋四没有关西,做的项目多了,掌握的知识体系自然就会趋于完整。
本节复盘及知识点补充内容对应博客 Hi3531D调试手记(一):Linux开发环境搭建 第一节(以太网服务器搭建在后面补充)。
下图是一种典型的嵌入式 Linux 操作系统开发环境的系统设置。首先,系统包含一个主机开发系统,用来运行 Linux 发行版。Linux 发行版的作用是提供开发环境和开发平台,因此系统类型和版本号没有硬性需求,只是需要在主机开发系统中需要包含开发工具和实用工具,以及由嵌入式 Linux 发行版提供的目标文件。嵌入式 Linux 目标板通过 RS-232 串行通信电缆与主机开发系统相连,同时主机开发系统也通过以太网与本地以太网集线器连接。
在为嵌入式系统开发应用程序或设备驱动程序之前,需要一套工具(编译器、二进制工具等)来为我们的目标系统生成可执行的二进制代码。考虑一下 PC 上的简单应用程序,例如比较典型的 “Hello World” 例子。当在 PC 上编完源码之后,需要调用编译器来生成可运行的二进制代码。这套二进制代码最终将运行在编译它的主机上,这称为本机编译,它的意思是使用本机的编译器进行编译,产生出的代码也运行于本机之上。
在交叉开发环境中开发软件,其实就是要让本机运行的编译器产生出不兼容于本机的可执行二进制格式(也就是在主机开发系统上生成,在目标板上运行)。交叉开发工具存在主要原因是资源的限制(内存大小、CPU 性能),在嵌入式系统中做本地化的软件开发和编译是不现实的,也是不可能的。
PS:这里仅仅补充了交叉开发工具的概念。实际上还有 GDB、DDD 等许多非常实用的工具在 Linux 应用开发的调试中起着非常重要的作用。但是 GDB 这个东西确实不是两三句话就能说得清的,
而且第一次项目也没用到 GDB 调试看以后时机成熟了再单独开坑记录一下。
本节复盘及知识点补充内容对应博客 Hi3531D调试手记(Ex):U-Boot使用随笔 中的 U-Boot 信息记录(内核的启动与初始化为额外补充)。
在桌面计算机上电后,一种叫做 BIOS(Basic Input/Output Software) 的软件系统会立即接管对系统处理器的控制,完成系统的硬件检查与初始化任务,然后将操作系统从 PC 的硬盘驱动器中读出并加载。通常,BIOS 保存在闪存(Flash)内,以便之后能对 BIOS 进行必要的升级工作。
引导装入程序(bootloader)就相当于是存在于典型嵌入式系统中的 BIOS,因此 bootloader 在嵌入式系统中的地位不言而喻。开发人员的一部分开发工作,就是要开发出针对特定开发板的引导装入程序。幸运的是,由于市面上可以购买到现成的开发板,如果是以此为基础来开发嵌入式系统的相关应用程序,就可以直接从店家手中获取到对应于开发板的固件程序(包括 bootloader 在内)。
U-Boot 就是 bootloader 中使用最为广泛的一种,咱的 Hi3531D 使用的 bootloader 就是 U-Boot。
PS:上电即运行,有没有感觉 bootloader 就是个裸机程序?自信点,把感觉去掉,引导装入程序听起来是有点高大上的样子,但是通俗来说就是个用来做初始化工作裸机程序。
以 Hi3531D 的启动为例,U-Boot 在完成系统启动准备工作的过程中会通过串行通信端口回传一些信息:
可以看出在 Hi3531D 上电后,U-Boot 执行了一系列底层硬件的初始化工作,包括配置串行通信端口,之后通过串口输出了上图中的信息,比如 U-Boot 的版本信息以及开发板特性的文本信息。这些信息都是 U-Boot 的开发者在源代码中加入的。最后一行 “Hit any key to stop autoboot: 0” 是执行自动启动的倒计时显示。如果没有在计数自然归零之前主动打断,则会在那之后进入启动内核的阶段。
如果打断了自启动倒计时,U-Boot 就会进入控制台模式,等待用户输入指令,此时可以看到命令提示符 hisilicon #。实际上控制台模式已经属于开发人员拉取出来的配置接口了,一般用户可以在 U-Boot 控制台模式下直接输入启动指令来启动 linux(其实自启动也是自动调用内核启动指令),也可以预先配置好一些启动参数,设置好网络环境,利用 tftp 预先将 linux 内核镜像与根文件系统下载到开发板上实现独立启动,又或者利用 nfs 直接将主机开发系统上的 linux 内核镜像与根文件系统挂载到开发板上,当然要是在这里就展开的话那就扯远了。
PS:U-Boot 控制台模式下提供了不少可用的命令。然而咱在使用 Hi3531D 的时候必须在 U-Boot 阶段配置的东西其实是比较有限的,主要工作也就是烧录内核镜像、根文件系统以及设定启动方式是独立启动还是网络挂载启动了,就连 U-Boot 本身也是基本不用进行版本更新的。因为是主做应用开发,这一块确实没有花太多时间,除非是硬件上的改动,否则即便真的需要修改开发环境的配置,那也多是在 linux 内核镜像那边配置。
自启动倒计时结束后,U-Boot 剩下的唯一工作就是加载并启动 Linux 操作系统内核。在 Loading Kernel Image … OK 信息之后的单独一行 OK 即宣告 U-Boot 使命的结束,Linux 操作系统内核从 U-Boot 手中接管所有的内存以及系统资源,此后的启动信息均由 Linux 内核产生。
当 Linux 内核开始执行以后,它将向控制台输出大量状态信息,以便用户了解系统的启动过程。在 Hi3531D 开发板的启动过程中,Linux 内核至少输出了超过 100 行的信息,直到显示系统登陆提示符。这里只贴出 Linux 内核显示的最后几行信息,因为当前还不适合对内核初始化的细节进行详细讨论(内核的启动信息分析的内容足够再单独开一篇博客,这里牵扯到的东西太多了,先不说自己有没有接触到这方面的知识点,即便接触到了一篇博客肯定也写不完)。
这里只需要注意,在控制台终端显示登陆提示符之前,Linux 操作系统内核挂载了根文件系统。根文件系统通常包含很多应用程序、系统库以及组成 GNU/Linux 的各种实用工具。
Linux 挂载根文件系统的方法有好几种,其中最常见的方式就是直接在系统的硬盘空间中挂载根文件系统,就像常见的桌面 Linux 工作站那样;以及使用 NFS 服务挂载主机开发系统上存放的根文件系统。事实上,NFS 的挂载功能是调试的利器 —— 它使得开发人员彻底避免了微调内核或是根文件系统的配置后就必须重新烧录进开发板运行才能验证修改结果的麻烦,即是说,在主机开发系统上更改了内核或是根文件系统的配置,开发板上启动时加载的镜像文件会通过 NFS 直接同步,无需烧录。
在前一节的演示图中的最后一行输出信息:Freeing unused kernel memory: 232K (c0596000 - c05d0000) 释放了未使用的内核虚拟内存(虚拟内存的概念参考 如何理解虚拟内存 - 知乎)。或许现在还看不出什么,但是补充完接下来的知识点,或许这一行信息所表现出来的意义就不一样了。
现在应该不难看出,本节开头提及的最后一行输出信息预示着系统从内核态到用户态的切换:内核完成了所有内部初始化工作并且挂载了根文件系统后,释放掉了空闲的内核虚拟内存,开始运行在用户空间上下文中。此后再有输出的信息,就是由“其他东西”产生的了。
PS:这里的“其他东西”在后面还会提及,到时候一并说了,就不在这里拆解说明。
本节复盘及知识点补充内容对应博客 Hi3531D调试手记(二):U-Boot、Linux内核与RootFS镜像制作及烧录 中的 U-Boot 相关内容以及博客 Hi3531D调试手记(一):Linux开发环境搭建 、博客 Hi3531D调试手记(Ex):U-Boot使用随笔 中的网络环境配置。
在编译 U-Boot 之前,首先会对 U-Boot 进行一些预先的配置,使用命令:
make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- hi3531d_xxx_config
实际上这两种参数是有对应的配置文件的,就存放在 ./include/configs 子目录中:
打开 hi3531d.h,能够发现里面主要都是两种形式的配置变量:使用 CONFIG_XXX 形式的宏选择配置项和使用 CFG_XXX 形式的宏选择配置项。一般来说,CONFIG_XXX 形式的配置选项是用户可以根据具体需求自行配置的;CFG_XXX 形式的配置选项通常和硬件相关,需要理解处理器和硬件平台的内部细节才能做出合理的配置,不清楚的话不去动它就完了。下图就是预设 U-Boot 控制台模式的环境变量的部分配置内容:
通过使用这种机制,可以配置 U-Boot 的很多方面,包括编译哪些功能,比如支持 DHCP、内存测试、调试等(没错,甚至可以配置 U-Boot 控制台下能使用哪些命令)。这种机制也可以用来告知 U-Boot,开发板上使用了哪种内存,以及内存大小和内存映射地址。多的这里就不展开了,点到为止,各个配置选项的详细情况可以去阅读 U-Boot 的 README 文件。
问题记录:
实际上,真正完整的流程还包括 U-Boot 编译之前的 U-Boot 移植。不过因为博主的项目采用的方案是直接在 Hi3531D 开发板上做软件开发工作,完了在硬件上按开发板裁剪并仿制出自己的板子,再把之前做好的平台与应用整套搬过来,姑且算是取了个巧(因为从店家手上拿到的其实已经算是移植好了的),所以对于 U-Boot 移植的具体情况还是模糊的。如果以后再接手到不能如此取巧的开发项目,再回来仔细研究移植吧。
另外,对于利用编译得到的 u-boot.bin 文件和 mkboot.sh 来生成最终可用的 U-Boot 镜像这一步自认为没弄明白,也只是简单地照做了。目前能找到的资料有限 (其实就是完全没找到) ,配合使用的 Excel 表格也只能大致看出来是关于寄存器级别的参数设置,mkboot.sh 将包含这些寄存器配置信息的 reg_info.bin 文件内容整合到 u-boot.bin 文件中,从而得到完整的 U-Boot 镜像文件。不过也不确定这是否为海思 SDK 包独有的机制,只能先作为一个疑点记录下来。
现在回到对 U-Boot 进行预配置的指令中。可选参数:使用 SPI Nor Flash 或 SPI Nand Flash 以及 使用 Nand Flash,这两种参数对应了不同的配置。虽说当时因为板载资源只有 SPI Nor Flash 和 SPI Nand Flash,莫得选择,只能用第一种,但是这块的知识点是空白的,现在补上。
首先,Flash 本身是一种非易失性存储,在没有电流供应的条件下也能够长久地保持数据,其存储特性相当于硬盘,这项特性正是闪存得以成为各类便携型数字设备的存储介质的基础。Flash按照内部存储结构的不同,可以分为两种:Nor Flash 和 Nand Flash。
其次,在 Hi3531D 开发板中已经有 U-Boot 且网络配置完成的情况下,可以使用网口将新的 U-Boot 、Linux 内核映像以及根文件系统烧写到 Flash 中。开发板默认为从 SPI Flash 启动。下图中并没有记录关于 U-Boot 烧录的指令内容,但是完全可以根据另外两个烧写的命令反推得到。
上图中的指令是 SPI Nor Flash 的烧写方法,但是咱板子上 SPI Nor Flash 和 SPI Nand Flash 又是同时存在的!如果要用 SPI Nand FLash 的话,烧录指令就不一样了:
PS:烧录的文件系统的类型也不一样了,但是这个现在不是当前重点,之后会展开。另外,只要处理器支持,将启动介质设置为 SPI Nor Flash/SPI Nand Flash/并口 Nand Flash 都是可行的,但涉及到硬件电路上的设置以及 U-Boot 配置上的修改。
最后,还有一点关于博客 Hi3531D调试手记(二):U-Boot、Linux内核与RootFS镜像制作及烧录 中 U-Boot 启动参数设置的说明补充:
setenv bootargs 'mem=64M console=ttyAMA0,115200 root=/dev/mtdblock2 rootfstype=jffs2 rw mtdparts=hi_sfc:1M(boot),4M(kernel),27M(rootfs);hinand:256M(nand)'
这里是将 U-Boot、Linux 内核以及根文件系统镜像都烧写到了 SPI Nor Flash 里,所以前三个分区都是使用 hi_sfc 来进行空间划分。然而之后又跟了一句 hinand:256M(nand),将 SPI Nand Flash 也用上了,个人认为或许和嵌入式系统中的闪存结构图有关。
通常情况下,U-Boot 会安排在闪存阵列的最顶端或者最底端,Linux 内核映像以及文件系统映像紧随其后,其中,Linux 内核映像以及文件系统映像都是压缩过的,U-Boot 在启动过程中负责对它们进行解压。
为了存储在重启或重新上电情况下需要保存的动态数据,需要专门分配一小块闪存空间,或者提供另外一种非易失存储介质。对于需要保存配置信息的嵌入式系统来说,这是很典型的配置形式。Hi3531D 的 SPI Nor Flash 有 32M,已经全部分配给 U-Boot、Kernel 和 RootFS 这前三个分区,那么 256M 的 SPI Nand Flash 作为另一种非易失存储介质,在这里应该就是作为更新空间使用了。
许多 bootloader 都包括了对以太网接口的支持(U-Boot 也不例外)。在开发环境中,这会极大地节省时间。通过串口载入一个中等规模的内核镜像可能需要数分钟之久,而使用 10Mbit/s 的以太网连接器仅需要几秒钟。此外,使用功能较弱的串行终端的串口连接更容易产生错误。
Hi3531D 开发板对应的 U-Boot 支持 TFTP(Trivial File Transfer Protocol)协议和 NFS(Network File System)服务,这就使得 U-Boot 能通过 TFTP/NFS 服务器下载文件(例如 Linux 内核镜像)/直接挂载文件系统。
U-Boot 阶段的网络环境变量配置的知识点就不补充了,计算机网络基础知识。
在 Linux 开发主机上配置 TFTP 服务并不难。当然,根据开发工作站选择的 Linux 发行版的不同,其配置细节也有差异。这里就以 Ubuntu 为例进行记录。
TFTP 是一种 TCP/IP 服务,因此工作站必须开启 TCP/IP 服务。要开启 TFTP 服务,必须指示服务器响应即将到来的 TFTP 数据包,并创建 TFTP 服务器。在使用 apt-get 安装好指定软件包以后,原博客中一共记录了三处修改:/etc/xinetd.conf 、/etc/default/tftpd-hpa 以及 /etc/xinetd.d/tftp,接下来对逐个文件的修改进行说明。
使用 NFS 挂载目标板 Linux 内核镜像和根文件系统是非常有效的开发手段。不知道是不是因为使用到的 NFS 功能很有限,感觉 Ubuntu 下搭建 NFS 服务器似乎异常地简单,只需要修改一处:/etc/exports。
本节复盘及知识点补充内容对应博客 Hi3531D调试手记(一):Linux开发环境搭建、Hi3531D调试手记(二):U-Boot、Linux内核与RootFS镜像制作及烧录 中的 Linux 内核相关内容。这里补充得比较多,毕竟之前让内核启动了就直接开始开发软件了,对于内核这一块的细节是真的没关注太多。
在很多地方都可以轻而易举地得到 Linux 内核源代码以及其他组件。书店所售 Linux 图书中附带的光盘就有很多种不同的版本。当然也可以从 Linux 内核的官方主页 www.kernel.org 下载不同版本的 Linux 内核源码以及各种补丁。
Hi3531D 项目的开发使用的 Linux 内核版本为 3.18。在很早以前的开发者队伍中,从事开发工作的工程师们为了能够区分 Linux 内核源码树,使用数字来对其进行编号。Linux 内核可以分为两大类:一类是专门用于开发的试验版本,另一类是稳定的产品级版本。Linux 操作系统的版本号由主版本号和次版本号组成,最后还有相应的序列号。如果小版本号是偶数,则表明此版本的 Linux 操作系统是稳定的产品级产品;如果是奇数,则表明此版本的 Linux 操作系统是用于开发的试验产品。
想要了解正在使用的 Linux 内核版本信息是很容易的。在内核源码的最顶层 Makefile 前几行中就包含了当前操作系统的内核版本,例如下面的几行信息,从这几行信息中可以看到,Linux 是 3.18.20 版本的产品级内核。
EXTRAVERSION 这一栏是空的,用于留给用户自定义字段实现在开发过程中对内核版本的快速跟踪与定位。
当前主机开发系统上有两个版本的 Linux 内核:一个是要通过交叉编译最终运行在 Hi3531D 开发板上的 3.18.20 版本(图示为已完成编译的状态);另一个则是主机开发系统上使用的 Linux 发行版的内核,相应的内核源码在 /usr/src/linux-x.y.z 路径下,其中 x.y.z 表示当前 Linux 内核的版本号。
可以看到,Linux 内核的顶层目录包含了众多的子目录,而通常这些子目录还包含了其他几层子目录,里面包含了源代码、makefile 以及配置文件。所有 Linux 内核源码树中最大的就是 driver 路径下的内容,这里面包含了支持以太网卡、USB 控制器以及 Linux 内核所支持的所有硬件驱动是程序以及源代码。第二大分支自然就是 arch 子目录,它包含了至少 20 多种不同类型的处理器体系结构的支持文件。
除了这些子目录,顶层 makefile、.config 文件以及 System.map 文件和 vmlinux 文件都是非常重要的文件,具体情况在补充说明 Linux 内核编译过程的时候展开。
在完成 Linxu 内核代码的解压后,并未立即开始编译,而是先使用 patch 命令打了个补丁:
这里其实只完成了打补丁的后半部分工作(补丁文件已经放在 SDK 包里了)。完整的打补丁过程,是先将源文件复制出一个副本,在副本里面修改,修改完成后使用 diff 命令比较两个文件之间的差异,得到补丁文件,再用 patch 命令使补丁生效,则源文件就会更改成副本的样子。当然,也可以把补丁去掉,变成原来的样子。
PS:补丁文件里的内容很多,而且以目前的水平来看是理解不能的,这个只能放一放。
.config 文件包含了编译 Linux 内核映像的一系列配置脚本,因此被放置于 Linux 操作系统资源路径的顶层,用于驱动整个系统内核的构建工作。它是进行操作系统内核编译的起点,特别是针对某种嵌入式平台完成 Linux 内核编译的工作。
这里直接将对应处理器型号的 defconfig 文件直接拷贝过来作为初始的 .config 文件:
因为当前的 .config 文件只能算是 Hi3531D 的默认配置,所以如果需要对内核进行自定义功能的选择,就可以通过接下来的指令完成:
接下来就会进入到配置界面:
如果需要使用 NFS 挂载根文件系统,也需要在这里设置内核支持才行。
补充:
menuconfig 只是更新 .config 文件的其中一种图形界面化工具。实际上还可以使用 xconfig、gconfig、oldconfig、randconfig 等多种方式来修改 .config 中的内核配置信息。如果需要更详细的说明,可以直接使用 make help 指令获取,当然这样的话实际输出的信息量可能远远超出原本使用这条指令的预期:
PS:你以为这就完了?其实只是贴了前面的一小部分截图而已。指令中加上了 ARCH=arm 来声明 make 的目标归属于 ARM 架构。如果有兴趣可以试试不加声明,看看最后输出的信息有什么不同。
在使用指令编译完 Linux 内核以后,可以看到在末尾处生成了几个文件,分别是 vmlinux、zImage 和对应的 dtb、uImage:
这些文件的意义可以通过 make help 来查看:
因此,vmlinux 实际上才是严格意义上的 Linux 内核,它是一个完全独立运行的单一操作系统内核映像,所有的外部引用信息都保存在 vmlinuix 二进制文件中(因此理解 vmlinux 的二进制组件构成也是理解 linux 启动流程的关键);zImage 是一般情况下经过压缩的内核映像;uImage 则是配合 U-Boot 使用的 zImage,二者并没有本质上的区别。
本节复盘及知识点补充内容对应博客 Hi3531D调试手记(二):U-Boot、Linux内核与RootFS镜像制作及烧录 中的根文件系统相关内容。
这是个在嵌入式 Linux 中非常有用的一个强力工具。但是在当前阶段博主接触到的直接原因是用来制作根文件系统,所以还是决定把它给放在这里简单地介绍一下。
BusyBox 提供一些紧凑的程序,可以替代那些大多数桌面和嵌入式 Linux 发行版中使用的成熟实用程序,例如 ls、cat、dir、head 和 tail 等文件工具;dmesg、kill、halt、mount、umount 等常用实用程序,不一而足。
BusyBox 具有模块化和高度可配置的特点,可以进行裁剪以满足项目的特定需求。BusyBox 提供的实用配置程序与配置 lInux 内核所用的实用程序类似,因此 BusyBox 的配置非常容易上手。
与对应的全功能版本相比,BusyBox 里的命令实现一般更为简单。在某些情况下,BusyBox 仅支持一部分常用的命令行选项。但是,实际上 BusyBox 提供的命令功能子集足以满足绝大多数嵌入式系统的常见需求。
inittab 是 Linux 系统初始化过程中需要使用到的一个文件,内核启动后就需要读取其内容来决定在最开始要创建哪些进程。基于 BusyBox 构建跟文件系统,也就是由 BusyBox 来处理系统初始化,也需要这样一个文件。但是,BusyBox 初始化系统使用到的 inittab 与 System V 初始化系统使用到的 inittab 文件在语法上有区别的,二者并不能混为一谈。
fstab 是用来存放文件系统的静态信息的文件,位于 /etc/ 目录下,可以用命令 less /etc/fstab 来查看。如果要修改的话,则用命令 vi /etc/fstab 来修改。当系统启动的时候,系统会自动地从这个文件读取信息,并且会自动将此文件中指定的文件系统挂载到指定的目录。
在 BusyBox 产生一个交互 Shell 之前(也就是用户看见命令提示符之前),会执行名为 /etc/init.d/rcS 脚本文件中的命令。在一个基于 BusyBox 的系统中,用户的应用程序就是在这个脚本文件中得以实现,正如博客 Hi3531D调试手记(四):使用ffmpeg实时封装H264视频为MP4 的第五节:杂记(个人向)中所描述的那样。
文件系统是操作系统用于明确存储设备(常见的是磁盘,也有基于 NAND Flash 的固态硬盘)或分区上的文件的方法和数据结构;即在存储设备上组织文件的方法。操作系统中负责管理和存储文件信息的软件机构称为文件管理系统,简称文件系统。文件系统由三部分组成:文件系统的接口,对对象操作和管理的软件集合,对象及属性。从系统角度来看,文件系统是对文件存储设备的空间进行组织和分配,负责文件存储并对存入的文件进行保护和检索的系统。具体地说,它负责为用户建立文件,存入、读出、修改、转储文件,控制文件的存取,当用户不再使用时撤销文件等。简单来说,内核是 linux 的核心,而文件系统则是用户与操作系统交互所采用的主要工具。
根文件系统是文件系统中的一种特殊形式,它是内核启动时所挂载的第一个文件系统,是后续挂载的所有文件系统的 “根”。内核代码映像文件也保存在根文件系统中,系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行(比如之前的 rcS 文件)。
Linux 启动时,第一个必须挂载的是根文件系统。若系统不能从指定设备上挂载根文件系统,则系统会出错而退出启动。根文件系统挂载成功之后,用户也可以设置自动或手动挂载其他的文件系统。因此,一个系统中可以同时存在不同的文件系统。在 Linux 中将一个文件系统与一个存储设备关联起来的过程称为挂载(mount)。使用 mount 命令将一个文件系统附着到当前文件系统层次结构中(根)。在执行挂装时,要提供文件系统类型、文件系统和一个挂装点。根文件系统被挂载到根目录下“/”上后,在根目录下就有根文件系统的各个目录,文件:/bin /sbin /mnt 等,再将其他分区挂接到 /mnt 目录上,/mnt 目录下就有这个分区的各个目录和文件。
这个东西可能直接上表来看会更为直观:
文件系统类型 | 优点 | 缺点 |
---|---|---|
cramfs | 将文件数据以压缩形式存储,在需要运行时进行解压缩,能节省 Flash 存储空间。 | 由于其存储的文件是压缩的格式,所以文件系统不能直接在 Flash 上运行。同时,文件系统运行时需要解压数据并拷贝至内存中,在一定程度上降低了读取效率。另外 cramfs 文件系统是只读的。 |
jffs2 | 使用了压缩的文件格式。最重要的特性是可读写操作。 | jffs2 文件系统挂载时需要扫描整个文件系统,因此当 jffs2 文件系统分区增大时,挂载时间也会相应的变长。使用 jffs2 格式可能带来少量的 Flash 空间的浪费。这主要是由于日志文件的过度开销和用于回收系统的无用存储单元,浪费的空间大小大致是若干个数据段。jffs2 的另一缺点是当文件系统已满或接近满时,其运行速度会由于垃圾收集问题而迅速降低。 |
yaffs2 | 专门针对 Nand Flash,软件结构得到优化,速度快;使用硬件的 spare area 区域存储文件组织信息,启动时只需扫描组织信息,启动比较快;采用多策略垃圾回收算法,能够提高垃圾回收的效率和公平性,达到损耗平衡的目的。 | 没有采用压缩的文件格式。当包含的内容相同时,yaffs2 镜像文件要比 jffs2 镜像文件大。 |
这篇文章就到这里吧,目前的篇幅已经很长了,然而这里记录的不过是些皮毛而已 QAQ … 整篇看下来可能会有些杂乱无章的感觉,但这就是个人学过来最真实的写照:大概知道分成几大块,再从这些大块发散式地学习与补充相关知识点。
驱动开发和 Makefile 的部分放在下一篇博客中记录。