自动加载内核模块
像许多操作系统一样,Linux 提供了对众多设备、文件系统和网络协议的支持。不幸的是,这种不断增长的支持增加了内核的内存需求。Linux 通过允许在编译内核时仅选择您需要的功能,部分地解决了这个问题。通过允许将某些功能编译为模块,从而可以仅在需要时加载它们,这得到了进一步的改进。模块的加载和卸载可以使用 kerneld 自动化,使得使用编译为模块的功能就像使用包含在基本内核中的功能一样容易。
要使用 kerneld,您应该首先安装最新版本的模块包,该软件包可在 www.pi.se/blox/modules/ 找到。我正在使用 modules-1.3.69f,但在您阅读本文时,可能已经有更新的版本了。此外,您还需要至少与 1.3.57 一样新的内核。
幸运的是,kerneld 自动了解大多数模块。您只需在启动脚本中运行它即可。对于基于 Slackware 的系统,您需要编辑 /etc/rc.d/rc.local。您应该包含以下内容
# Update kernel-module dependencies file [ -x /sbin/depmod ] && { /sbin/depmod -a } # Start kerneld [ -x /sbin/kerneld ] && { /sbin/kerneld }
对于 Red Hat 系统,您可以在 ftp.redhat.com 的 /pub/contrib/RPMS/ 中安装贡献的模块 RPM,名为 modules-1.3.57-3.i386.rpm,它提供对 kerneld 的支持。在您阅读本文时,可能会发布更新的版本,因此如果您在那里找不到它,请查找更高版本的模块实用程序。或者,阅读 LJ 第 27 期(1996 年 7 月)中的文章“了解 Red Hat 运行级别”,并在 /etc/init.d 中创建一个 kerneld 启动脚本,并在 /etc/rc2.d、/etc/rc3.d、/etc/rc4.d 和 /etc/rc5.d 中创建适当的链接。
在任何一种情况下,这都会运行 depmod,它会更新 kerneld 使用的依赖信息,然后启动 kerneld,kerneld 会派生并隐藏在后台,直到内核需要它。
现在,您只需重新配置您的内核,以便为您不经常使用的功能使用模块,并构建和安装内核和模块。如果您以前从未构建过模块,只需在内核编译过程中添加两个步骤:make modules 和 make modules_install。
当您启动新内核时,您应该让所有模块在您尝试使用它们时自动加载。命令 lsmod 将告诉您哪些模块已加载。当然,最好保留您的旧内核可启动,以防出现意外情况。
不幸的是,kerneld 并不了解您可能想要安装的每个模块——特别是那些不属于内核发行版的模块。要安装这些模块,您需要在 /etc/conf.modules 中告诉 kerneld 关于它们的信息。Kerneld 需要知道模块的存放位置以及触发加载它的事件。
我强烈建议您为您的模块使用默认目录。否则,您不仅需要将新路径添加到 /etc/conf.modules,还需要添加所有默认路径。要查看默认路径,请使用 modprobe -c | more。
告诉 kerneld 什么触发模块的加载需要添加 /etc/conf.modules 中的 alias 条目。对于设备驱动程序,例如 zftape.o 或 joystick.o,格式基于设备类型(字符或块)和主编号。例如,我为操纵杆驱动程序使用 alias char-major-15 joystick。您可以通过运行 modprobe -c 来查看默认值,从而获得大量示例。如果存在应触发加载同一模块的多个事件,则可以为同一模块设置多个条目。
如果您想加载可选模块,例如使用 PPP 的 BSD 压缩,您可能还需要设置别名。用于 BSD 压缩的最简单的别名是 alias ppp bsd_comp。这将告诉 kerneld 加载 bsd_comp 而不是 ppp,但由于 bsd_comp 需要真正的 ppp 模块(这需要 slhc),它将首先加载 slhc 和 ppp。当然,如果您对此有疑问,您可以始终在您的拨号脚本中显式加载模块,并在 /etc/ppp/ip-down 中卸载它们。
您还可以使用 kerneld 设置按需拨号网络连接。当内核收到向没有路由信息的 IP 地址发送数据包的请求时,它会询问 kerneld 是否可以建立到该地址的路由。当 kerneld 收到此类请求时,它会运行 /sbin/request-route,这通常应该是一个启动 PPP 或 SLIP 的脚本,从而建立路由。
因此,您所要做的就是将 /sbin/request-route 替换为您的拨号脚本。嗯... 不完全是。如果您完全依赖外部名称服务器,您可能会侥幸成功。但是,总的来说,您需要小心,因为 kerneld 可能会多次调用 request-route,内核需要解析的每个 IP 地址调用一次。这可以通过为调制解调器设备使用锁定文件来解决,这是 chat 和 pppd 的一个选项。[无论如何,您应该使用该选项!—ED]
在配置系统时,起初您可能会认为最好将所有内容都编译为模块。但这并不总是好的主意,因为它并不总是节省内存。每个模块在 4K 页中使用内存,因此最后一页通常会浪费一些空间。因此,如果您几乎总是会使用该模块,您不妨将其编译到内核中。此外,请记住,kerneld 本身会消耗一些内存(根据我的经验,至少 12 页),因此,如果您只有几个小型模块需要担心,最好将它们编译到内核中,或者在启动脚本中显式加载它们。
只要文件系统已挂载,文件系统的模块就必须加载,即使您没有使用它。因此,如果您始终保持挂载 /dos,请不要费心将对 FAT 的支持编译为模块。如果您不喜欢该选项,您可以考虑使用自动挂载守护程序而不是保持文件系统挂载。
小心那些包含在运行时可能会更改的信息的模块。例如,声音驱动程序会跟踪音量,如果您将其编译为模块,则每次加载时音量都会重置为默认值。
最后,请注意不要将某些东西编译为模块,如果它将在 kerneld 启动之前在启动时使用。这当然包括根文件系统。对于许多系统,您会发现您需要在 kerneld 启动之前同时支持 ELF 和 a.out。您可以通过将 kerneld 安装为启动脚本执行的首批程序之一来克服某些问题,但如果您还在进行按需拨号,请小心,因为您的启动脚本中可能有类似 sendmail 的东西会触发它。只要您保留旧内核作为安全网,就可以随意尝试。
Preston Crow Preston Crow 是达特茅斯学院计算机科学专业的研究生。他在 1995 年夏天成为一名快乐的 Linux 用户,不久之后就幸福地结婚了。