initng(init nextgerneration)能够并行启动服务从而快速完成初始化工作。initng认为满足了依赖关系的服务就可以启动。在从外存加载一个脚本或等待硬件设备启动的同时,可以运行另一个脚本来启动别的服务,使系统在 CPU 和 I/O 之间实现较好的平衡。作为一个基于依赖关系的解决方案,initng 使用自己的初始化脚本集,它们对服务和守护进程的依赖性进行了编码。如果某个服务依赖(使用 need 关键字定义)于其他服务,则要保证启动时它所依赖的所有服务均可用。无依赖关系的服务立即并行启动,具有依赖关系的服务则要等待以安全启动。
ELF(Excutable and Linkable File)是目前Linux中的标准二进制格式,其启动需要以下步骤:将共享库映射到虚拟地址空间;解析符号引用;初始化每个ELF文件。由于共享库是位置无关的,要在运行时完成部分重定位处理和符号查找的工作,才能跳到程序的入口点,因此在带来灵活性的同时,也造成ELF文件的启动速度缓慢,尤其是解析符号引用要消耗大量的时间,对于使用多个共享库的大型程序更是如此。但在很多嵌入式系统中,可执行文件和共享库极少变化,而且每次程序运行时链接工作完全相同。
嵌入式系统中代码的执行方式主要有3种:
① 完全映射(fully shadowed)。嵌入式系统程序运行时,将所有的代码从非易失存储器(Flash、ROM等)复制到RAM中运行。
② 按需分页(demand paging)。只复制部分代码到RAM中。这种方法对RAM中的页进行导入/导出管理,如果访问位于虚存中但不在物理RAM中会产生页错误,这时才将代码和数据映射到RAM中。
③ eXecute In Place (XIP)。在系统启动时,不将代码复制到RAM,而是直接在非易失性存储位置执行。RAM中只存放需要不断变化的数据部分,如图1所示。如果非易失性存储器的读取速度与RAM相近,则XIP可以节省复制和解压的时间。NOR Flash和ROM的读取速度比较快(约100 ns),适合XIP;而NAND Flash的读操作是基于扇区的,速度相对很慢(μs级),因此不宜实现XIP。
图1 完全映射和XIP的比较
XIP可以分为以下2种:
① 内核XIP。直接在Flash/ROM中运行内核,可以节省复制和映像解压的时间。Linux 2.6.10内核已经包含了XIP支持。
② 应用程序XIP。直接从应用程序代码的存储位置执行,而不用将它加载到RAM中,这样应用程序的第一次执行速度会比较快。要使用应用程序XIP,应该基于支持它的文件系统。
Linear XIP CRAMFS的一个缺陷在于它是基于文件的,即一个文件中的所有页要么全部采用XIP,要么全部采用压缩/按需分页,但事实上同一文件中不同页的使用频率区别也很大。AXFS是Intel公司开发的一个新的只读文件系统,它从Linear XIP CRAMFS中继承了许多方法,同时也进行了一些改进。AXFS的XIP粒度是基于页的,并且自带工具来判断哪些页需要XIP,哪些页需要压缩,从而更好地在速度和RAM/Flash的使用上取得平衡。