kerneld mini-HOWTO 1.7 版,上次由 Henrik Storner [1](storner@osiris.ping.dk)於 1997 年 7 月 19 日(storner@osiris.ping.dk) 更新。 曾达康 [2](a9504480@graduate.hku.hk) 於 1998 年 6 月 14 日完成翻译。 _________________________________________________________________ 导言 此文件解释如何使用 Linux 核心中的 kerneld 功能。它会说明: * [3]kerneld 是什麽 * [4]为什麽要用它 * [5]如何取得所需东西 * [6]如何设定它 * [7]如何告诉 kerneld 它不认识的模组的资料 * [8]如何侦察 kerneld (设定时可能有用) * [9]kerneld 的特别用途 * [10]常见问题及怪事 此文件的最新版本可在 [11]http://eolicom.olicom.dk/~storner/kerneld-mini-HOWTO.html 找到。( 译按:中文版则可在 [12]http://www.linux.org.tw/CLDP/mini/Kerneld.html 找到)在此 mini-HOWTO 推出的正式版本期间,你可在 [13]http://eolicom.olicom.dk/~storner/kern.html 找到未经组织的更新清单 。 荣誉 如果你发现此文件中出现错误,请告诉文章的原作者。以下各人都曾对本文作出 贡献: * Bjorn Ekwall * Ben Galliart * Cedric Tefft * Brian Miller * James C. Tsiao 我非常感谢此 mini-HOWTO 读者寄给我们的鼓励和提议。 (译按∶当然,如果问题出在译文中,请通知曾达康 ) _________________________________________________________________ kerneld 是什麽? kerneld 是由 [14]Bjorn Ekwall 引入 1.3 版的发展核心 (development kernel) 的功能。它可在所有 2.0 及 2.1 版本的核心找到。它令模组 (modules)—即驱动程式 (device drivers)、网络驱动器 (network drivers)、 档案系统 (filesystems)—自动在有需要时载入,而不需自行使用 modprobe 或 insmod。 还有更有趣的东西,虽然它们尚未整合到标准的核心中∶ * 它可设定成不使用内定的空白画面,而让你选择其他程式,使你可自选萤幕 保护器 (screen saver)。 * 和萤幕保护器相似,你可把主控台 (console) 的‘哔’声改为完全不同的东 西… kerneld 包括两个独立部分: * 核心向监控程式 (daemon) 就所需模组提出要求的支援。 * 懂找出所需模组来满足核心要求的使用者层面 (user-level) 监控程式。 要使用 kerneld,两个部分都要正常运作。只设定好其中一个是没用的。 _________________________________________________________________ 为什麽要用它? 有不少好理由去使用 kerneld。这里提出的是我个人的——其他人可能有其他的 理由。 * 如果你要为多个只有少许不同的系统(如使用不同的网络控制卡)建立核心 ,你只需建立一个核心和数个模组,而不需为每个系统建立不同的核心。 * 对开发人员而言,模组比较容易测试—你不需重新启动电脑以载入及卸下驱 动程式(这点适用於所有模组,并不限於 kerneld 载入的)。 * 它减少核心占用的记忆体,即你有更多记忆体供其他程式使用。核心所占用 的记忆体是 *永不* 被换出 (swap-out) 的,所以如果你的核心中有 100kB 没用的驱动程式的话,那只是在浪费你的记忆体。 * 有一些我要用的东西,如 ftape floppy-tape driver 或 iBCS,只以模组形 式出现。但我懒得自己载入和卸下它们。 * Linux 发行者不再需要建立 284 个不同的开机影象 (boot images) —使用 者只载入配合其硬件的驱动程式。例如 RedHat 4.0 就使用了这方法。 当然,你也有不使用它的理由—你可能喜欢在一个核心映象 (kernel image) 中 包括所有你要的驱动程式。如果是这样,你看错文章了。 _________________________________________________________________ 如何取得所需东西? 对 kerneld 的支援始於 1.3.57 版。如果你正使用较旧的版本,你需要更新它才 可用 kerneld 了。所有主要的 Linux ftp 台都有核心的原程式码。我建议你更 新至最新版本的稳定核心,2.0,目前是嵌补等级 (patch level) 2.0.29 (译按 :现时已是 2.0.35): [15]ftp://sunsite.unc.edu/pub/Linux/kernel/v2.0/linux-2.0.29.tar.gz [16]ftp://tsx-11.mit.edu/pub/linux/sources/system/v2.0/linux-2.0.29.tar.gz [17]ftp://ftp.funet.fi/pub/Linux/PEOPLE/Linus/v2.0/linux-2.0.29.tar.gz 使用者层面的监控程式包含在 modules-1.2.8 及更新的 modules-2.0 中。它们 一般会和核心源程式码在同一地点找到,而官方位置包括: [18]ftp://sunsite.unc.edu/pub/Linux/kernel/v2.0/modules-2.0.0.tar.gz [19]ftp://tsx-11.mit.edu/pub/linux/sources/sbin/modules-2.0.0.tar.gz [20]ftp://ftp.funet.fi/pub/Linux/tools/modules-2.0.0.tar.gz 注意:如果你想在 2.1 版的开发核心尝试载入模组,你必须用最新的 modutils-(不是 modules-)。但请看 [21]以下有关模组和 2.1 版核心部分的 问题。 _________________________________________________________________ 如何设定它? 首先要取得所需的东西:合用的核心部分及最新版的 modules-utilities。之後 你要安装 modules-utilities。十分简单:只需把原程式码解压及执行 make install. 这样便会编译 genksysm, insmod, lsmod, modprobe, depmod, kerneld,及把它们安装到 /sbin。我建议你加数行到你的开机命令手稿 (startup-script) 来完成启动时所需的设定。如果你使用 Slackware,请把以下 数行加入你的 /etc/rc.d/rc.S 档,如果你使用 SysVinit,如 Debian, RedHat, Caldera,请把以下数行加入你的 /etc/rc.d/rc.sysinit 档。(译按: 据我所知,RedHat 5.0的 SysVinit已加入此功能): # Start kerneld - this should happen very early in the # boot process, certainly BEFORE you run fsck on filesystems # that might need to have disk drivers autoloaded if [ -x /sbin/kerneld ] then /sbin/kerneld fi # Your standard fsck commands go here # And you mount command to mount the root fs read-write # Update kernel-module dependencies file # Your root-fs MUST be mounted read-write by now if [ -x /sbin/depmod ] then /sbin/depmod -a fi 第一部分启动 kerneld。 第二部分开始时执行 'depmod -a'。depmod 建立所有可找到的模组的清单及分析 它们之间互相依赖的情况。所以,它会知道载入一个模组前是否需要先载入其他 模组。 注意∶最新版本的 kerneld 可选择链结 (link) GNU 的 dbm 程式库 libgdbm。 如果在编译 module-utilities 时作了此抉择,找不到 libgdbm 时 kerneld 便 不能启动。这很有可能当 /usr 在另一个磁碟分区 (partition),而企图在挂 (mount) /usr 前启动 kerneld 时发生。建议的解决方法是把 libgdbm 从 /usr/lib 移到 /lib,或静态连结 kerneld (link kerneld statically)。 之後,你要把核心的源程式解压,设定及建立一个你喜欢的核心。如果你未试过 这样做,你必须阅读在 Linux 源程式码顶层目录 (top directory) 中的 README 档。在执行 make config 设定核心时,你要注意数条在早期出现的问题 : Enable loadable module support (CONFIG_MODULES) [Y/n/?] Y 你要选择 loadable module support,否则根本不会有模组让 kerneld 载入。答 Yes。 Kernel daemon support (CONFIG_KERNELD) [Y/n/?] Y 当然,这也是需要的,很多东西都可建立为模组。你会见到类似的问题: Normal floppy disk support (CONFIG_BLK_DEV_FD) [M/n/y/?] 你可回答 'M' 来代表模组。通常只有开机时必须的驱动程式,如硬碟机驱动程式 ,和根目录的档案系统等必需建立在核心中。其他皆可建立为模组。 完成 'make config' 後,执行 'make dep', 'make clean', 'make zImage' 或 'make zlilo', 'make modules' 和 'make modules_install'。 成功! 'make zImage' 会把你的新核心映像 (kernel image) 放到 arch/i386/boot/zImage。你要把它拷贝到你放置启动映像的地方或用 LILO 安装 它。 想得到更多有关设定,建立及安装核心部分的资料,请阅读定时贴上 comp.os.linux.answers 的[22]Kernel-HOWTO ,你也可在 sunsite.unc.edu 的 /pub/Linux/docs/HOWTO 找到它。(译按:中文版可在 [23]http://www.linux.org.tw/CLDP/Kernel-HOWTO.html找到。) _________________________________________________________________ 试用 kerneld 现在你可用新的核心部分开机。在系统启动後,执行 'ps -ax',你应该会见到 kerneld 的一行: PID TTY STAT TIME COMMAND 59 ? S 0:01 /sbin/kerneld kerneld 其中一个好处是只要你有所需的核心及安装好监控程式,你只需作很少 设定。现在,你可尝试用一个建立成模组的驱动程式—它多数会不需再作设定而 能使用。我把软磁碟的驱动程式建立成模组,所以我放入一只 DOS 磁碟及 osiris:~ $ mdir a: Volume in drive A has no label Volume Serial Number is 2E2B-1102 Directory for A:/ binuti~1 gz 1942 02-14-1996 11:35a binutils-2.6.0.6-2.6.0.7.diff.gz libc-5~1 gz 24747 02-14-1996 11:35a libc-5.3.4-5.3.5.diff.gz 2 file(s) 26689 bytes 即是说软磁碟的驱动程式运作正常—当我尝试使用软磁碟时,它被自动载入。 要看到软磁碟的模组真的被载入,你可执行 /sbin/lsmod,它会列出现时载入了 的模组。 osiris:~ $ /sbin/lsmod Module: #pages: Used by: floppy 11 0 (autoclean) "(autoclean)" 代表如果有一分钟没用此模组,它就会被 kerneld 自动移走。所 以,那 11 页记忆体(44 kB,一页等於 4kB)只会在我使用软碟机时被占用。如 果我一分钟不用软碟,它会被释放。如果你的记忆体不敷应用,这就太棒了! _________________________________________________________________ kerneld 如何知道该载入什麽模组? 虽然 kerneld 本身对常用的模组有所认识,有时它会不知如何应付核心提出的要 求。例如光碟机驱动程式或网络驱动程式等可能需要超过一个模组的情形。 kerneld 从核心部分会收到以下种类的要求: * [24]区块设备驱动程式 (a block-device driver) * [25]字元设备驱动程式 (a character-device driver) * [26]二元格式 (a binary format) * [27]tty 连线规则 (a tty line discipline) * [28]档案系统 (a filesystem) * [29]网络设备 (a network device) * 网络服务 (a network service),如 rarp * [30]网络协定 (a network protocol),如 IPX kerneld 从架构档案 (configuration file) /etc/conf.modules 中得知有什麽 模组需要载入。这里有两类项目:路径 (paths)(模组档案的位置)和代号 (aliases)(要载入什麽模组)。如果你未有此档,你可用以下方法自己制造: /sbin/modprobe -c | grep -v '^path' >/etc/conf.modules 如果你想加多一个路径到预定路径中,你必须包括所有现有的路径。因为在 /etc/conf.modules 里的一个路径项目会取代 所有 modprobe 内置的路径! 通常你是不用自己加上路径的,因为预设的路行将己照顾到所有正常的设定。我 可保证! 另一方面,如果你只想加入代号 (alias) 或者选项 (option directive),你在 /etc/conf.modules 的新项目会加入到 modprobe 所知的。如果你想再定义一个 代号或选择,你在 /etc/conf.modules 中的项目会凌驾预设那个。 区块设备 如果你执行 '/sbin/modprobe -c',你会得到一个 kerneld 已知的模组的名单及 它们所对应的要求。例如,导致载入软碟驱动程式的要求是主号码 (major number) 是 2 的区块设备。 osiris:~ $ /sbin/modprobe -c | grep floppy alias block-major-2 floppy 为什麽是 block-major-2?因为软碟设备 /dev/fd* 的主号码 (major number) 是 2 ,又是区块设备。 osiris:~ $ ls -l /dev/fd0 /dev/fd1 brw-rw-rw- 1 root root 2, 0 Mar 3 1995 /dev/fd0 brw-r--r-- 1 root root 2, 1 Mar 3 1995 /dev/fd1 字元设备 字元设备的方法处理也差不多。例如 ftape floppy tape driver 的是 major-device 27: osiris:~ $ ls -lL /dev/ftape crw-rw---- 1 root disk 27, 0 Jul 18 1994 /dev/ftape 但 kerneld 本身并不知道 ftape 驱动程式,它不会在 '/sbin/modprobe -c' 的 结果中出现。 所以,要使 kerneld 载入 ftape 驱动程式,我要加一行到 kerneld 的设定档 /etc/conf.modules 中: alias char-major-27 ftape 网络设备 你也可以用设备的名称来代替那些 'char-major-xxx' 或 'block-major-yyy' 设 定。这样对网络设备尤其有用,例如把 ne2000 网络卡用作 eth0 可以籍此载入 : alias eth0 ne 如果你需要传递一些选项给你的驱动程式,例如告诉模组这网络卡使用什麽 IRQ ,你可加上如下一 'options' 行: options ne irq=5 这样会使 kerneld 用以下指令来载入 NE2000 驱动程式∶ /sbin/modprobe ne irq=5 当然,实际上所用的选项会因应所用模组而有所不同。 二元格式 二元格式也以相似的方法处理。每当你尝试执行一个核心不懂载入的程式 ,kerneld 便会收到一个 "binfmt-xxx" 的要求, xxx 是一个由档案开头数个字 元决定的数字。使 kerneld 为 ZMAGIC (a.out) 执行档载入 binfmt_aout 模组 的设定是: alias binfmt-267 binfmt_aout 因为 ZMAGIC 档的幻数 (magic number) 是 267。(如果你查看 /etc/magic,你 会见到 0413 这个数字,但 /etc/magic 使用八进位数 (octal numbers) 而 kerneld 使用十进数 (decimal),而八进位的 413 即十进数的 267。)由於 a.out 格式共有三款稍为稍为不同的可执行档 (NMAGIC, QMAGIC and ZMAGIC), 要全面支援 binfmt_aout 模组我们需要 alias binfmt-264 binfmt_aout # pure executable (NMAGIC) alias binfmt-267 binfmt_aout # demand-paged executable (ZMAGIC) alias binfmt-204 binfmt_aout # demand-paged executable (QMAGIC) kerneld 可自动辨认 a.out, Java 和 iBCS 二元格式,毋须特别设定。 连线规则 (slip, cslip and ppp) 连线规则用 "tty-ldisc-x"来作要求,而 x 一般是 1 (slip) 或 3 (ppp) 。kerneld 本身都认识这两样。 说起 ppp,如果你想 kerneld 载入 bsd_comp 资料压缩模组,你需要加两行到 /etc/conf.modules 中: alias tty-ldisc-3 bsd_comp alias ppp0 bsd_comp 网络协定 (IPX, AppleTalk, AX.25) 部分网络协定也可以模组载入。核心要用到一个网络家族 (network family)(如 IPX)时,会向 kerneld 作出对一个类似 "net-pf-X" 的要求,而 X 是一个代表 所属家族的数字。例如 net-pf-3 是 AX.25,net-pf-4 是 IPX,而 net-pf-5 是 AppleTalk。(这些数字是由 linux 源程式档 include/linux/socket.h 中 AF_AX25, AF_IPX 的定义而来的。)故此要自动载入 IPX 模组,你要加一个类似 以下的项目到 /etc/conf.modules 中: alias net-pf-4 ipx 也请阅读以下有关防止开机时出现关於未定义的协定的[31]常见问题。 档案系统 有关档案系统的 kerneld 要求就是档案系统的名称。一个常见的用途是为光碟载 入 isofs 的模组,例如 "iso9660" 档案系统: alias iso9660 isofs _________________________________________________________________ 需要特别设定的设备 部分设备不只要使用代码 (aliasing),还要其他设定,如模组的设备 (a device to a module)。 * 主数码 10 的字元设备:[32]杂项设备 (The miscellaneous devices) * [33]SCSI 设备 * [34]需特别初始化 (initialization) 的设备 char-major-10:滑鼠、看门狗和随机数 (Mice, watchdogs and randomness) 大多数硬件设备都以主数码分辨,例如 ftape 是 char-major-27。但如果你看看 在 /dev 中主数码是 10 的字元设备,你会见到一堆毫无关连的设备,包括: * 各种各样的滑鼠(bus mice, PS/2 mice) * 看门狗设备 (watchdog devices) * 核心的 'random' 设备 * APM 介面 (Advanced Power Management interface) 很明显,这些设备是由多个不同的模组控制的。所以,这些杂项设备的 kerneld 设定用到主号码及副号码 (the major number and the minor number): alias char-major-10-1 psaux # For PS/2 mouse alias char-major-10-130 wdt # For WDT watchdog 要用到此特性,你需要一个 1.3.82 或之後的核心部分。较旧的核心不会把副号 码传给 kerneld,因此,kerneld 不能找出所需要的杂项设备。 载入 SCSI 驱动程式: scsi_hostadapter 项目 SCSI 设备包括一个 SCSI 配接卡 (SCSI host adapter, 例如 Adaptec 1542)及 一个所需设备(如硬碟机 (hard disk)、光碟机 (CD-ROM) 或磁带机 (tape-drive))的驱动程式。这全都可以模组来载入。但是,当你想存取连接到 Adaptec 卡的光碟机时,核心和 kerneld 只知道它需要载入 sr_mod 模组来支援 那 SCSI 光碟机—它不知道那光碟机连接到什麽 SCSI 控制器 (SCSI controller),所以不知道载入什麽模组来支援那光碟机。 要解决这问题,你可加一个你的 SCSI 驱动程式的项目到你的 /etc/conf.modules 中,籍以告诉 kerneld 如何在众多 SCSI 控制器模组中选择 : alias scd0 sr_mod # sr_mod for SCSI CD-ROM's ... alias scsi_hostadapter aha1542 # ... need the Adaptec driver 这只适用於 1.3.82 或之後的核心。 这方法只当你只用一个 SCSI 控制器时适用。如果你有超过一个,难度就高一点 。 一般来说,如果已经载入了一个配接器,你不能再叫 kerneld 载入另一个。你可 把两个都编译到核心中(不用模组),或自己把模组载入。 事实上,有一个方法可使 kerneld 载入多个 SCSI 驱动程式。James Tsiao 有以 下提议: 只要你亲手建立 modules.dep 的倚赖 (dependency),你可很轻易使 得 kerneld 载入第二个 SCSI 驱动程式。你只需一个类似的项目: /lib/modules/2.0.30/scsi/st.o: /lib/modules/2.0.30/scsi/aha1542.o 来使 kerneld 在载入 st.o 前先载入 aha1542.o。我家中的电脑就使用 了几乎相同的设定,对我所有二级 SCSI 设备 (secondary scsi devices), 包括磁带机、光碟机和其他一般的 SCSI 设备都没问题。缺点是 'depmod -a' 不能自动查出这些倚赖,所以你要自己加入这些,而且不 可在开机时执行 'depmod -a'。但只要设定好了,kerneld 就能自动载入 aha1542.o。 你要知道这技考只当你有不同种类的 SCSI 设备接驳在两个控制器时才有用,例 如,把硬碟驳在其中一个,而把光碟机、磁带或其他 SCSI 驳到另一个。 要载入超过一个模组时:“post-install”项目 有时,只把模组载入不足以使设备运作。例如,如果你把音效卡编译为模组,你 也会希望调整至适当音量。问题题你的设定在下次载入时便会失去。这里是由 Ben Galliart (bgallia@luc.edu) 提供的秘诀: 最终的解决方法需要安装 setmix-0.1 ( ftp://sunsite.unc.edu/pub/Linux/apps/sound/mixers/setmix-0.1.tar.gz ) 之後把以下一行加到我的 /etc/conf.modules: post-install sound /usr/local/bin/setmix -f /etc/volume.conf 这样,当音效的模组载入後,kerneld 会执行 'post-install sound' 项目的指 令。因此该模组会被 '/usr/local/bin/setmix -f /etc/volume.conf 指令设定 好。 这方法对其他模组也有用,例如 lp 模组可籍以下一句用 tunelp 程式设定好: post-install lp tunelp 只有 1.3.69f 版或之後的 kerneld 才支援这些选项。 注意: :此 mini-HOWTO 的较旧版本曾提及一个 "pre-remove" 选项,让你可在 kerneld 卸下一个模组时执行一个指令。但这从未成功,因此并不鼓励使用。这 个选项多数会在未来版本的 kerneld 中消失。所有有关模组 "设定" 的事情都在 改变中,在你看到这文件时,可能已有所不同了。 _________________________________________________________________ 侦察 kerneld 如果你什麽方法都已试过,但仍找不出核心在要在 kerneld 做什麽,你可用一个 方法找出 kerneld 收到什麽要求,从而知道该加什麽到 /etc/conf.modules。你 需要 kdstat 程式。 这个好用的程式已包括在 modules-package 中,但预定是不会编译及安装的。你 可用以下方法建立它: cd /usr/src/modules-2.0.0/kerneld make kdstat 之後,要使 kerneld 显示它正在做什麽,执行 kdstat debug kerneld 便会开始在主控台印出其工作的资料。当你执行所需的指令时,你会见 到 kerneld 收到的要求。这些要求可放到 /etc/conf.modules 中,加上所需模 组的别名 (alias),便可使工作完成。 要停止除错时,执行 '/sbin/kdstat nodebug'。 _________________________________________________________________ kerneld 的特殊用途 我知道你想问如何设定萤幕保护程式 (screensaver) 的模组… modules-package 的 'kerneld/GOODIES' 目录中有一些和萤幕保护程式及主控台 哔声支援有关的核心修补 (kernel patches)。它们尚未在官方的核心出现。所以 你要自行修正及重新编译核心。 要安装修补,你要用 "patch" 指令: cd /usr/src/linux patch -s -p1