bla*_*ker 6 kernel kernel-modules linux-kernel
我试图了解使用 Linux 内核模块的缺点。我了解使用它们的好处:能够将代码动态插入到正在运行的系统中,而无需重新编译和重新启动基本系统。鉴于这种强大的优势,我猜测大部分内核代码应该在内核模块中,而不是作为基本内核的一部分,但情况似乎并非如此——大量的核心子系统(如内存管理)仍然进入基础内核。
我能想到的一个原因是内核模块在引导过程中加载得很晚,因此核心功能必须在基本内核中。我阅读的另一个原因是关于碎片化。
我真的不明白为什么内核模块会导致内存碎片,有人可以解释一下吗?使用内核模块还有其他缺点吗?
是的,基本组件(例如mm)不能成为可加载模块的原因是因为它们是必不可少的——没有它们内核将无法工作。
我找不到任何声称内存碎片对可加载模块的影响很重要的参考文献,但是LLKM 操作方法的这一部分对您来说可能会很有趣。
我认为这个问题实际上是内存碎片问题的重要组成部分,通常发生在两个层面上:内核 mm 子系统管理的实际内存碎片,以及非常大的应用程序可能发生的虚拟地址空间碎片(我认为这主要是它们设计和编译方式的结果)。
关于实际内存的碎片,我认为这在比页面大小 (4 KB) 更精细的粒度下是不可能的。因此,如果您正在读取 1 MB 的虚拟连续空间,而该空间实际上 100% 碎片化为 1024 个页面,则可能涉及 1000 个额外的小操作。在这部分操作指南中,我们读到:
基本内核在其珍贵的连续域中包含一大片可重用内存——kmalloc 池。在某些版本的 Linux 中,模块加载器首先尝试从该池中获取连续的内存来加载 LKM,并且仅当没有足够大的空间可用时,才会转到 vmalloc 空间。Andi Kleen 于 2002 年 10 月提交了在 Linux 2.5 中执行此操作的代码。他声称差异在百分之几的范围内。
这里,vmalloc 空间(用户空间应用程序所在的位置)可能很容易碎片化为页面。这就是当代操作系统的现实(它们都通过虚拟寻址来管理内存)。我们可以从中推断出,虚拟寻址在用户空间中也可能代表“百分之几”的性能损失,但就虚拟寻址在用户空间中是必要且不可避免的而言,它仅与完全理论上的东西有关。
进程的虚拟地址空间(而不是其背后的实际内存)的碎片有可能进一步复合碎片,但这永远不会适用于内核模块(而最后一段显然可以)。
如果你想听我的意见,那不值得深思。请记住,即使使用高度模块化的内核,最常用的组件(文件系统、网络等)也往往会很早就加载并保持加载状态,因此它们肯定会位于实际内存的连续区域中,因为它是什么值得(这可能是不要无意义地加载和卸载模块的一个原因)。
对于单片内核,理论上可以为内核分配单个连续的内存块。如果按需加载(和卸载)模块,那么所有内核内存都不可能是连续的,因此根据定义,它会被分割。权衡是模块化内核通常会使用比单片内核少得多的内存。对于默认的发行版单体内核,这当然是正确的,它可能有许多未使用的驱动程序,但如果您构建自己的单体内核,则不太正确。
一些子系统根本不适合模块化,内存管理显然是一个,SMP 是另一个。进程调度不是模块化的,但 I/O 调度策略是。由于复杂的相互依赖关系,其他子系统可能不是模块化的,例如 TCP/IP。
模块的另一个问题是,如果它们驱动您需要从中启动的设备,它们就不是那么好,解决方案是initrd
解决这个问题。
最后一个考虑是安全性,允许加载模块是一个潜在的风险,例如像knark这样的内核可加载 rootkit 。请参阅http://www.la-samhna.de/library/rootkits/index.html和http://www.sans.org/security-resources/malwarefaq/Ptrace.php。您可以通过强制签名模块(自内核 3.7 起)、最后加载锁定模块或其他强化来降低这种风险。
归档时间: |
|
查看次数: |
3812 次 |
最近记录: |