Skip to content

Commit 347137b

Browse files
authored
revise the translation of "kernel modules" (#72)
1 parent ba68aa1 commit 347137b

File tree

1 file changed

+23
-23
lines changed

1 file changed

+23
-23
lines changed

labs/kernel_modules.rst

+23-23
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
内核模块概述
2020
===========
2121

22-
虽然单体内核比微内核更快,但缺乏模块化和可扩展性。在现代单体内核中,这个问题已经通过使用内核模块来解决。内核模块(或可加载内核模式)是一个包含代码的目标文件(object file),它可以在运行时扩展内核的功能(根据需要加载);当不需要内核模块时,可以卸载它。大多数设备驱动程序以内核模块的形式使用
22+
虽然单体内核的运行速度比微内核更快,但它在模块化和可扩展性方面存在不足。在现代的单体内核设计中,这个问题已经通过使用内核模块得到了解决。内核模块(或称为可加载内核模块)是一种包含代码的目标文件(object file),它可以在运行时根据需要加载,以扩展内核的功能;而当这些模块不再需要时,也可以将其卸载。大部分设备驱动程序都是以内核模块的形式实现的
2323

24-
为了开发 Linux 设备驱动程序,建议下载内核源代码,配置和编译它们,然后将编译后的版本安装在测试/开发工具机上。
24+
要想开发 Linux 设备驱动程序,建议下载内核源代码,配置和编译它们,然后将编译后的版本安装在测试/开发工具机上。
2525

2626
..
2727
_[SECTION-OVERVIEW-END]
@@ -32,7 +32,7 @@
3232
内核模块示例
3333
============
3434

35-
以下是一个非常简单的内核模块示例。当加载到内核中时,它会生成消息 :code:`"Hi"`。当卸载内核模块时,将生成消息 :code:`"Bye"`。
35+
以下是一个非常简单的内核模块示例。当加载到内核中时,它会生成消息 :code:`"Hi"`。当卸载这个内核模块时,将生成消息 :code:`"Bye"`。
3636

3737
.. code-block:: c
3838
@@ -59,7 +59,7 @@
5959
module_exit(dummy_exit);
6060
6161
62-
生成的消息不会显示在控制台上,而是保存在专门预留的内存区域中,由日志守护程序(syslog)负责将其提取出来。要显示内核消息,你可以使用 `dmesg` 命令或检查日志文件。
62+
生成的消息不会显示在控制台上,而是保存在专门预留的内存区域中,由日志守护程序(syslog)负责将其提取出来。要显示内核消息,你可以使用 :command:`dmesg` 命令或检查日志文件。
6363

6464
.. code-block:: bash
6565
@@ -80,7 +80,7 @@
8080
编译内核模块
8181
============
8282

83-
编译内核模块与编译用户程序不同。首先,需要使用另外的头文件。此外,模块不应链接到库。最重要的是,模块必须使用与加载模块的内核相同的选项进行编译。出于这些原因,有一种标准的编译方法(kbuild)。该方法需要使用两个文件: :file:`Makefile` 文件和 :file:`Kbuild` 文件。
83+
编译内核模块与编译用户程序不同。首先,需要使用不同的头文件。此外,模块不应链接到库。最后,模块必须使用与加载模块的内核相同的选项进行编译。出于这些原因,有一种标准的编译方法(kbuild)。该方法需要使用两个文件: :file:`Makefile` 文件和 :file:`Kbuild` 文件。
8484

8585
以下是 :file:`Makefile` 文件的示例:
8686

@@ -103,16 +103,16 @@
103103
obj-m = modul.o
104104
105105
106-
正如你所见,在示例中调用 :command:`make` 命令对 :file:`Makefile` 文件进行编译将导致在内核源代码目录 (``/lib/modules/`uname -r`/build``) 中调用 :command:`make` 并引用当前目录 (``M = `pwd``)。该过程最终会读取当前目录中的 :file:`Kbuild` 文件,并按照该文件中的指示编译模块
106+
正如你所见,在示例中调用 :command:`make` 命令对 :file:`Makefile` 文件进行编译时,会在内核源代码目录 (``/lib/modules/`uname -r`/build``) 中执行 :command:`make` 命令,并引用当前目录 (``M = `pwd``)。这个过程最终会读取当前目录中的 :file:`Kbuild` 文件,并按照其中的指示编译模块
107107

108-
.. note:: 对于实验,我们将根据虚拟机的规格配置不同的 :command:`KDIR`:
108+
.. note:: 对于实验,我们将根据虚拟机的规格,配置不同的 :command:`KDIR`:
109109

110110
.. code-block:: bash
111111
112112
KDIR = /home/student/src/linux
113113
[...]
114114
115-
:file:`Kbuild` 文件包含一个或多个指令,用于编译内核模块。其中一个最简单的指令示例是 ``obj-m = module.o``。根据该指令,将从 ``module.o`` 文件开始创建一个内核模块( :code:`ko` ,即 :code:`kernel object`,也就是内核对象)。``module.o`` 将基于 ``module.c`` 或 ``module.S`` 创建。所有这些文件都可以在 :file:`Kbuild` 所在的目录中找到
115+
:file:`Kbuild` 文件包含了一系列指令,这些指令用于编译内核模块。其中一个最基本的指令例子是 ``obj-m = module.o``。遵循这个指令,系统会基于 ``module.o`` 文件开始构建一个内核模块(也称为 :code:`ko`,即内核对象)。``module.o`` 文件是基于 ``module.c`` 或 ``module.S`` 生成的。所有这些文件都应该存放在包含 :file:`Kbuild` 的同一目录下
116116

117117
下面是一个使用多个子模块的 :file:`Kbuild` 文件示例:
118118

@@ -132,14 +132,14 @@
132132

133133
:file:`Kbuild` 中目标(target)的后缀决定了它们的用途,如下所示:
134134

135-
* M(modules) 标示目标为可加载内核模块
135+
* M(modules)标示目标为可加载内核模块
136136

137-
* Y(yes) 表示目标是用于编译并链接到模块(``$(模块名称)-y``)或内核(``obj-y``)的对象文件
137+
* Y(yes)标示目标是编译对象文件然后将其链接到模块(``$(模块名称)-y``)或内核(``obj-y``)
138138

139139
* 其他任何目标后缀都将被 :file:`Kbuild` 忽略,不会被编译
140140

141141

142-
.. note:: 这些后缀使得可以通过运行 :command:`make menuconfig` 命令或直接编辑 :file:`.config` 文件来轻松配置内核。该文件设置了一系列变量,用于确定在构建时向内核添加哪些特性。例如,使用 :command:`make menuconfig` 命令添加 BTRFS 支持时,:file:`.config` 文件中添加行 :code:`CONFIG_BTRFS_FS = y`。BTRFS kbuild 包含了一行 ``obj-$(CONFIG_BTRFS_FS):= btrfs.o``,它会转变成 ``obj-y:= btrfs.o``。这将编译 :file:`btrfs.o` 对象,并将其链接到内核。如果没有设置变量,该行会转变成 ``obj:=btrfs.o``,然后被忽略,进而内核构建时不会包含 BTRFS 支持。
142+
.. note:: 借助这些后缀,开发者可以通过运行 :command:`make menuconfig` 命令或直接编辑 :file:`.config` 文件来轻松配置内核。该文件设置了一系列变量,这些变量决定了在构建过程中哪些特性会被添加到内核中。例如,当使用 :command:`make menuconfig` 命令添加 BTRFS 支持时,:file:`.config` 文件中会增加 :code:`CONFIG_BTRFS_FS = y` 这一行。BTRFS kbuild 包含了一行 ``obj-$(CONFIG_BTRFS_FS):= btrfs.o``,如果设置了相应的变量,这行代码会变成 ``obj-y:= btrfs.o``。这将导致系统编译 :file:`btrfs.o` 对象,并将其链接到内核中。如果没有设置该变量,这行代码则会变成 ``obj:= btrfs.o`` 并被忽略,结果是内核构建时不会包含 BTRFS 支持。
143143

144144
要了解更多详细信息,请参阅内核源代码中的 :file:`Documentation/kbuild/makefiles.txt` 和 :file:`Documentation/kbuild/modules.txt` 文件。
145145

@@ -159,7 +159,7 @@
159159
$ insmod module.ko
160160
$ rmmod module.ko
161161
162-
加载内核模块时,将执行 ``module_init`` 宏(macro)参数指定的函数。同样,当卸载模块时,将执行 ``module_exit`` 宏参数指定的函数
162+
加载内核模块时,将执行 ``module_init`` 宏参数指定的例程。同样,当卸载模块时,将执行 ``module_exit`` 宏参数指定的例程
163163

164164
下面是一个完整的编译、加载和卸载内核模块的示例:
165165

@@ -206,7 +206,7 @@
206206
内核模块调试
207207
===========
208208
209-
与调试常规程序相比,调试内核模块要复杂得多。首先,内核模块中的错误可能导致整个系统阻塞。因此,故障排除的速度会大大降低。为了避免重新启动,建议使用虚拟机(qemu、virtualbox 或者 vmware)。
209+
与调试常规程序相比,调试内核模块要复杂得多。首先,内核模块中的错误可能导致整个系统阻塞。因此,故障排查的速度会大大降低。为了避免重新启动,建议使用虚拟机(qemu、virtualbox 或者 vmware)。
210210
211211
当插入包含错误的模块到内核中时,它最终会生成一个 `内核 oops <https://zh.wikipedia.org/wiki/Oops_(Linux内核)>`_ 。内核 oops 是内核检测到的无效操作,只可能由内核生成。对于稳定的内核版本,这几乎可以肯定意味着模块含有错误。在 oops 出现后,内核仍将继续工作。
212212
@@ -307,19 +307,19 @@
307307
BUG: unable to handle kernel paging request at 00001234
308308
EIP: [<c89d4005>] my_oops_init + 0x5 / 0x20 [oops]
309309
310-
告诉我们错误的原因和生成错误的指令的地址。在我们的例子中,这是对内存的无效访问。
310+
告诉我们错误的原因和造成错误的指令的地址。在我们的例子中,这是对内存的无效访问。
311311
312312
接下来的一行是:
313313
314314
``Oops: 0002 [# 1] PREEMPT DEBUG_PAGEALLOC``
315315
316-
告诉我们这是第一个 oops(#1)。在这个上下文中,这很重要,因为一个 oops 可能会导致其他 oops。通常只有第一个 oops 是相关的。此外,oops 代码( ``0002`` )提供了有关错误类型的信息(参见 :file:`arch/x86/include/asm/trap_pf.h` ):
316+
告诉我们这是第一个 oops(#1)。在这个上下文中,这很重要,因为一个 oops 可能会导致其他 oops。通常只有第一个 oops 是相关的。此外,oops 代码(``0002``)提供了有关错误类型的信息(参见 :file:`arch/x86/include/asm/trap_pf.h` ):
317317
318-
* Bit 0 == 0 表示找不到页面,1 表示保护故障
319-
* Bit 1 == 0 表示读取,1 表示写入
320-
* Bit 2 == 0 表示内核模式,1 表示用户模式
318+
* 第 0 位 == 0 表示找不到页面,1 表示保护故障
319+
* 第 1 位 == 0 表示读取,1 表示写入
320+
* 第 2 位 == 0 表示内核模式,1 表示用户模式
321321
322-
在这种情况下,我们有一个写入访问导致了 oops(bit 1 1)。
322+
在这种情况下,我们有一个写入访问导致了 oops( 1 位为 1)。
323323
324324
下面是寄存器的转储(dump)。它解码了指令指针 (``EIP``) 的值,并指出错误出现在 :code:`my_oops_init` 函数中,偏移为 5 个字节(``EIP: [<c89d4005>] my_oops_init+0x5``)。该消息还显示了堆栈内容和到目前为止的调用回溯。
325325
@@ -451,11 +451,11 @@ objdump
451451
c89d4026: 90 nop
452452
c89d4027: 90 nop
453453
454-
请注意,生成 oops 的指令(先前确定为 ``c89d4005`` )是:
454+
请注意,生成 oops 的指令(先前确定为 ``c89d4005``)是:
455455
456-
```C89d4005: c7 05 34 12 00 00 03 movl $ 0x3,0x1234``
456+
``C89d4005: c7 05 34 12 00 00 03 movl $ 0x3,0x1234``
457457
458-
这正是预期的结果 - 将值 3 存储在地址 0x0001234 上。
458+
这正是预期的结果——将值 3 存储在地址 0x0001234 上。
459459
460460
:file:`/proc/modules` 用于查找加载的内核模块的地址。:command:`--adjust-vma` 选项允许你相对于 ``0xc89d4000`` 位置显示指令。:command:`-l` 选项将显示源代码中每行的编号,源代码与汇编语言代码交错显示。
461461
@@ -798,7 +798,7 @@ KDB 具有各种命令来控制和定义被调试系统的上下文:
798798
这些命令将构建当前实验骨架中的所有模块。
799799
800800
.. warning::
801-
在解决练习 3 之前,编译 ``3-error-mod`` 时会出现编译错误。为了避免此问题,删除 :file:`skels/kernel_modules/3-error-mod/` 目录,并从 ``skels/Kbuild`` 中删除相应的行。
801+
在解决练习 3 之前,编译 ``3-error-mod`` 时会出现编译错误。为了避免此问题,请删除 :file:`skels/kernel_modules/3-error-mod/` 目录,并从 ``skels/Kbuild`` 中删除相应的行。
802802
803803
使用 :command:`make console` 启动虚拟机,并执行以下任务:
804804

0 commit comments

Comments
 (0)