根据维基百科关于initrd的文章"许多Linux发行版都发布了一个通用的内核映像 - 发行版的开发人员打算在尽可能广泛的硬件上启动。此通用内核映像的设备驱动程序作为可加载模块包含在内,因为将许多驱动程序静态编译到一个内核中会导致内核映像大得多,可能太大而无法在内存有限的计算机上启动。这就提出了在引导时检测和加载挂载根文件系统所需的模块的问题,或者就此而言,推断根文件系统的位置或内容。为了避免将如此多的特殊情况的处理硬编码到内核中,使用了带有临时根文件系统(现在称为早期用户空间)的初始启动阶段。此根文件系统可以包含用户空间帮助程序,这些辅助程序执行挂载真正的根文件系统所需的硬件检测、模块加载和设备发现。"
我的问题是,如果我们添加在 initrd 中加载实际文件系统所需的模块等,而不是在实际的内核映像中保存保存,那么在 Bootpimage 的情况下,我们将实现什么,其中内核和 initrd 组合在一起形成一个引导映像。即使使用 initrd,内核的大小也会增加。
有人可以澄清吗?
定义"内核的大小"。
是的,如果你有一个最小的内核映像和一个充满数百个模块的 initrd,它可能会比编译所有内容的等效内核占用更多的总存储空间,所有模块标头等等。但是,一旦启动,确定它在什么硬件上,加载一些模块并丢弃所有其余模块(initrd 中的 init),它将占用更少的内存。另一方面,全内置内核映像一旦启动,内存中仍然与磁盘上一样大,浪费了所有不需要的驱动程序代码的空间。
存储几乎总是比 RAM 便宜得多且更丰富,因此在系统运行后以减少可用内存为代价来优化存储空间通常有点愚蠢。即使对于网络引导,为了稍微快一点的引导而牺牲总映像大小的运行时功能也毫无意义。这些考虑可能具有任何优点的少数几种系统几乎肯定不会首先使用通用多平台内核。
大小有几个方面,这可能会令人困惑。
-
磁盘/网络上的二进制大小
-
启动时间大小
-
运行时间大小
TL-博士;将 initrd 与模块结合使用可为通用映像提供当前 (3.17) Linux 内核代码的最小运行时内存占用量。
我的问题是,如果我们添加在 initrd 中加载实际文件系统所需的模块等,而不是在实际的内核映像中保存保存,那么在 Bootpimage 的情况下,我们将实现什么,其中内核和 initrd 组合在一起形成一个引导映像。即使使用 initrd,内核的大小也会增加。
您是正确的,因为无论您选择哪种机制,都将传输相同数量的数据。 事实上,加载模块的 initrd 将比完全静态链接的内核大,并且引导时间会更慢。 听起来很糟糕。
专门为设备构建的定制内核,不包含额外的硬件驱动程序或模块支持,始终是最好的。 Debian 内核编译手册给出了两个原因,即用户可能想要制作自定义内核。
- 通过功能最小化来限制安全问题的风险。
- 优化内存消耗
第二个选项通常是最关键的参数。 尽量减少正在运行的内核消耗的内存量。 initrd(或initramfs)是作为RAM磁盘加载的二进制磁盘映像。 它是所有用户代码,其单一任务是探测设备并使用模块加载来获取系统的正确驱动程序。 完成此作业后,它将挂载真正的引导设备或普通的根文件系统。 发生这种情况时,将丢弃 initrd 映像。
initrd 不消耗运行时内存。 您将获得通用映像和具有相当小的运行时占用空间的映像。
我会说发行版人员所做的努力有时会产生性能问题。 通常,ARM 驱动程序仅针对一个 SOC 编译;虽然源支持SOC族,但只能通过条件选择一个。 在最近的内核中,ARM 驱动程序始终支持整个 SOC 系列。 内存开销最小。 但是,对低级别驱动程序传递函数使用函数指针可能会限制控制器的带宽。
缓存刷新例程具有多缓存选项。 函数指针会导致编译器自动溢出。 但是,如果针对特定缓存类型进行编译,则编译器可以内联函数。 这通常会生成更好、更小的代码。 大多数驱动程序没有这种类型的基础结构。 但是,如果您编译针对 CPU 优化的整体内核,您将有更好的运行时行为。 几个关键的内核函数将使用内联函数。
驱动程序在编译到内核中时通常不会更快。 许多系统支持通过USB,PCMCIA,SDO等进行热插拔。 这些系统在模块加载方面也具有内存优势。