From 068a2dc6bcd12854627b9345b233cfb362573294 Mon Sep 17 00:00:00 2001 From: Felix Lee Date: Tue, 19 Sep 2023 13:09:35 +0800 Subject: [PATCH] fix typos untill 4.4 section --- lkmpg_cn.tex | 97 +++++++++++++++++++++++++++------------------------- 1 file changed, 50 insertions(+), 47 deletions(-) diff --git a/lkmpg_cn.tex b/lkmpg_cn.tex index 22006ce..e3fa701 100644 --- a/lkmpg_cn.tex +++ b/lkmpg_cn.tex @@ -162,8 +162,8 @@ Felix Lee ,基于《Linux 内核编程指南》英文版内 \label{sec:kernelmod} 参与 Linux 内核模块的开发需要具备 C 编程语言基础,以及有创建用于进程执行的传统% -程序的记录。这种追求深入研究了一个领域,其中不受监管的指针,如果被忽视,可能会% -潜在地触发整个文件系统的彻底消除,进而导致需要完全重新启动系统的情况。 +程序的记录。这需追求深入研究了一个领域,其中如果忽视不受监管的指针,可能会% +潜在地触发整个文件系统的彻底消除,进而导致需要完全重新启动系统的情况发生。 Linux 内核模块被精确地定义为,在内核需要时,能够在内核中动态加载和卸载的代码段。% 这些模块在不需要重新启动系统的情况下,能增强内核的能力。一个值得注意的例子是设% @@ -176,7 +176,7 @@ Linux 内核模块被精确地定义为,在内核需要时,能够在内核 Linux 发行版将命令 \sh|modprobe|, \sh|insmod| 与 \sh|depmod| 放入一个软件包中。% -在 Ubuntu/Debian GNU/Linux 上,运行如带参数的命令: +在 Ubuntu/Debian GNU/Linux 上,运行如下带参数的命令: \begin{codebash} sudo apt-get install build-essential kmod \end{codebash} @@ -212,16 +212,16 @@ sudo lsmod | grep fat \section{在我们开始之前} \label{sec:preparation} -在我们深入研究代码之前,有些材料需要注意。差导存在于每个人的系统,与不同个体的% -方法,这是明显的事实。这个成功编译并加载的庆典``hello world''程序的成就,可能有% +在我们深入研究代码之前,有些材料需要注意。差异存在于每个人的系统,及不同个体的% +方法,这是明显的事实。这个成功编译并加载的庆祝\,``hello world''\,程序的成就,可能有% 时会带来挑战。令人欣慰的是,我们克服了首次尝试中的最初障碍,这为后续工作铺平了道% 路,以使其平顺地进行。 \begin{enumerate} \item 模块版本。 为一个内核编译的一个模块,如编译时内核版本与已启动内核不同时,模块将不% - 能加载,除非在内核中打 \cpp|CONFIG_MODVERSIONS| 选项。模块版本在本指南% - 稍后进行讨论。直到解决模块版本问题,本指南中的示例,如果运行于一个打开% + 能加载,除非在内核中打开 \cpp|CONFIG_MODVERSIONS| 选项。模块版本在本指南% + 稍后进行讨论。直到解决模块版本问题,本指南中的示例,如果运行在一个打开% 模块版本选项的内核上,可能不会正常工作。然而,大多数现有 Linux 发行版本% 的内核,都打开了模块版本选项。如果在加载模块时,由于版本错误提升了难度,% 考虑编译一个使用关闭模块版本选项的内核。 @@ -242,7 +242,7 @@ sudo lsmod | grep fat 至附带默认内核配置,以支持 SecureBoot。在这种情况下,内核模块需要一个被% 签名的安全密钥。 - 如果失败,尝试插入你第一个``hello world''模块,这将产生消息 ``\emph{ERROR:% + 如果失败,尝试插入你第一个\,``hello world''\,模块,这将产生消息 ``\emph{ERROR:% could not insert module}''。如果在命令 \sh|dmesg| 中产生是这个消息 % \emph{Lockdown: insmod: unsigned module loading is restricted; see man % kernel lockdown.7},解决问题最简单的方法,是在你的 PC 或笔记本电脑上的启% @@ -263,17 +263,17 @@ sudo apt-get update apt-cache search linux-headers-`uname -r` \end{codebash} -这将告诉你什么内核头文件可用。那么如示例安装头文件: +这将告诉你什么内核头文件可用。那么如下面示例来安装头文件: \begin{codebash} sudo apt-get install kmod linux-headers-5.4.0-80-generic \end{codebash} -在 Arch Linux 发行版的系统上,运行: +在 Arch Linux 发行版的系统上,运行如下命令: \begin{codebash} sudo pacman -S linux-headers \end{codebash} -在 Fedora 发行版的系统上,运行: +在 Fedora 发行版的系统上,运行如下命令: \begin{codebash} sudo dnf install kernel-devel kernel-headers \end{codebash} @@ -282,7 +282,7 @@ sudo dnf install kernel-devel kernel-headers \label{sec:examples} 所有来自本文档的示例代码,都能从 \verb|examples| 子目录中找到。 -如果这里有任何编译错误,那么你可能需要一个更现代的内核版本,或需要安装相应的内% +如果这里有任何编译错误,那么你可能需要一个更为现代的内核版本,或需要安装相应的内% 核头文件包。 \chapter{Hello World} @@ -290,8 +290,8 @@ sudo dnf install kernel-devel kernel-headers \section{最简单的模块} \label{sec:org2d3e245} 大多数人通过某种"\emph{hello world}"示例来开始学习编程。我不清楚打破这个传统后%% -会对人们会发生什么,但我认为不出头是更为安全的。我们将开启一系列 hello world 编% -程旅程,来演示编写内核模块的基础的不同形态。 +会对人们会发生什么,但我深为认同``出头的椽子先烂''的古训。我们将开启一系列 hello % +world 编程旅程,来演示编写内核模块的不同形态基础知识。 这里可能是最简单的模块。 @@ -306,7 +306,8 @@ cd ~/develop/kernel/hello-1 \samplec{examples/hello-1.c} 现在你将需要一个 \verb|Makefile|。如果你拷贝并粘贴这些内容,并使用 \textit{tabs} % -符而不是空格符来替换行首的缩进,修改已经被粘贴的内容。 +符而不是空格符来替换行首的缩进,修改已经被粘贴的内容\footnote{以遵从 Makefile 文% +件编写规则,相关知识建议参阅 GNU Make 手册}。 \begin{code} obj-m += hello-1.o @@ -324,7 +325,7 @@ clean: (毕竟 \verb|-C| 选项会被处理,无论怎样)。查看更多关于 \verb|CURDIR| 信息,阅读 % \href{https://www.gnu.org/software/make/manual/make.html}{《GNU make 手册》}。 -最终,只直接运行 \verb|make|。 +最终,只要直接运行 \verb|make|。 \begin{codebash} make @@ -335,7 +336,9 @@ make 安全策略是 \verb|sudoers|。在 \verb|sudoers| 安全策略中,\verb|env_reset| 选项% 默认被打开,这个打开的选项会限制环境变量。尤其是,路径变量不会在用户环境中被保% 持,他们被设定为默认值(如了解更多信息,查看: \href{https://www.sudo.ws/docs/% -man/sudoers.man/}{sudoers 手册})。你可以通过下面命令来查看环境变量设置: +man/sudoers.man/}{sudoers 手册})。你可以通过下面命令\footnote{细心的读者,应能% +区分出运行这两次命令时,所使用的不同身份。这需要读者熟悉 Unix 命令行运行环境。% +}来查看环境变量设置: \begin{verbatim} $ sudo -s @@ -349,7 +352,7 @@ all: echo $(PWD) \end{code} -然后,我们可以使用 \verb|-p| 标记,从 Makefile 中打印出环境变量的值。 +然后,我们可以使用 \verb|-p| 标记,从 Makefile 中打印出环境变量的值。% \begin{verbatim} $ make -p | grep PWD @@ -422,8 +425,8 @@ $ sudo make -p | grep PWD } \end{enumerate} -如所有操作都如行云流水,那么你发现你已经有一个被编译的 \verb|hello-1.ko| 模块。 -你可使用下面命令来查看模块信息: +如所有操作都似行云流水,那么你发现已拥有一个被编译的 \verb|hello-1.ko| 模块。你% +可使用下面命令来查看模块信息: \begin{codebash} modinfo hello-1.ko \end{codebash} @@ -458,8 +461,8 @@ sudo journalctl --since "1 hour ago" | grep kernel 你现在知道关于创建,编译,安装与移除模块的基础。现在对模块如何工作做进一步说明。 模块至少需有两个函数:一个``开始''(初始化)函数,称为 \verb|init_module()|, -当模块用 \verb|insmod| 命令被加载到内核中时被调用,另一个``结束''(清除)函数,称% -为 \verb|cleanup_module()| 函数,录模块从内核被移除之前的时间点,其被调用。实际% +当模块用 \verb|insmod| 命令被加载到内核中时刻被调用,另一个``结束''(清除)函数,% +称为 \verb|cleanup_module()| 函数,当模块从内核被移除之前的时刻其被调用。实际% 上,该情况从内核 2.3.13 开始有所改变。你现在可以使用任何你喜欢的名称为模块的开% 始与结束函数命名,并且你将在 \ref{hello_n_goodbye} 节学习这样做。 事实上,新的方法是更令人偏爱的方法。 @@ -469,14 +472,14 @@ sudo journalctl --since "1 hour ago" | grep kernel 通常,\cpp|init_module()| 或者向内核注册来处理一些事务,或者用模块代码来替换内% 核函数之一(通常代码做些事务,并在之后调用最初被替换的函数)。% \verb|cleanup_module()| 函数被假定,无论 \verb|init_module()| 函数做什么,在移% -除模块时,该函数都做出相反的行为,只有这样模块可以被安全的卸载。 +除模块时,该函数都做出相反的行为,只有这样模块可以被安全卸载。 最后,每个内核模块需要引入 \verb|| 头文件。只有在我们需要宏扩展 % \verb|pr_alert()| 日志级别时,我们被需要引入头文件 \verb||。你% -将在小节 \ref{sec:printk} 中学习相关知识。 +将在 \ref{sec:printk} 节中学习相关知识。 \begin{enumerate} - \item 关于代码风格的一点。 + \item 强调关于代码风格的一点。 对每个开始内核编程的人来说,另一件不能立即察觉到的事,是在你的代码中使% 用 \textbf{制表符} 与 \textbf{非空格} 作为缩进。 它是内核编码的一种代码风格约定。 @@ -486,19 +489,19 @@ sudo journalctl --since "1 hour ago" | grep kernel \label{sec:printk} 开始之前,这里有个宏 \cpp|printk|,常伴随着一个优先级,如 \cpp|KERN_INFO| % 或 \verb|KERN_DEBUG|。 - 最近这些也可用一系列打印宏,用缩略形式而被表达,如 \verb|pr_info| 和 % + 最近这些也可用一系列缩略形式进行表达,如 \verb|pr_info| 和 % \verb|pr_debug|。这仅仅节省一些无脑的键盘敲击,并使用代码显得有些整洁。% - 他们可以 \src{include/linux/printk.h} 中找到。花些时间通读可用的优先级% - 宏的代码。 + 它们可以从 \src{include/linux/printk.h} 中找到。花些时间通读可用的优先% + 级的宏代码。 \item 关于编译。 内核模块的编译与普通用户空间应用程序的编译,有些许不同。早先的内核版本% - 需要我们留心这些配置,配置通常被存储在 Makefile 文件中。尽管分层被组组,% - 许多冗余配置在子目录的 Makefile 中被累积,这使得配置内容非常庞大并更难% - 于维护。幸运地是,这里有一种新方法来做这些事,被称为 kbuild,并且对于外% - 部可加载模块的编译过程,现在完全被集成到标准的内核编译机制中。要学习更% - 多关于如何编译模块的知识,不是官方内核的一部分内容(如你在本指南找到的所% - 有示例),查看文件 \src{Documentation/kbuild/modules.rst}。 + 需要我们留心这些配置,配置通常被存储在 Makefile 文件中。尽管 Makefile % + 被分层组组,许多冗余配置在子目录的 Makefile 中被累积,这使得配置内容非% + 常庞大并更难于维护。幸运地是,这里有一种新方法来做这些事,被称为 kbuild,% + 并且对于外部可加载模块的编译过程,现在完全被集成到标准的内核编译机制中。% + 要学习更多关于如何编译模块的知识,不是官方内核的一部分内容(如你在本指南% + 找到的所有示例),查看文件 \src{Documentation/kbuild/modules.rst}。 对内核模块来说,关于 Makefile 文件更细致的信息,可以从内核源代码中文件 % \src{Documentation/kbuild/makefiles.rst} 中找到。确保读过该文件以及相关% @@ -513,9 +516,9 @@ sudo journalctl --since "1 hour ago" | grep kernel \section{Hello\,与\,Goodbye} \label{hello_n_goodbye} 在早期内核版本中,你必须查看 \cpp|init_module| 与 \cpp|cleanup_module| 函数,如% -同在第一个 hello world 示例,但近些天你可以使用 \cpp|module_init| 和 % -\cpp|module_exit| 宏来任意命名这两个函数。这些宏在 \src{include/linux/module.h}% - 中被定义。唯一需要注意的是,在调用这些宏之前,你的初始化与清除函数必须已经被% +同在第一个 hello world 示例,但最近你可以使用 \cpp|module_init| 和 % +\cpp|module_exit| 宏来任意命名这两个函数。这些宏在 \src{include/linux/module.h} % +中被定义。唯一需要注意的是,在调用这些宏之前,你的初始化与清除函数必须已经被% 定义过,否则你将得到编译错误。这里有关于这个技术的一个示例: \samplec{examples/hello-2.c} @@ -544,19 +547,19 @@ clean: \section{\_\_init 与 \_\_exit 宏} \label{init_n_exit} -\cpp|__init| 宏引起 init 函数被丢弃,并且,对于嵌入驱动来说,一旦 init 函数结束,% -其点用的内存会被释放,但这不适用于可加载内核。当你思考当 init 函数被调用时有问% -题,这是完全有道理的。 +\cpp|__init| 宏引起 init 函数被丢弃,并且,对于内嵌驱动来说,一旦 init 函数结束,% +其占用的内存会被释放,但种情况这不适用于可加载内核。如果你思考当 init 函数被调% +用,这会产生完美的场景。 -这里也有一个 \cpp|__initdata| 宏,其工作与 \cpp|__init| 但只初始化变量,而不是% -函数。 +这里也有一个 \cpp|__initdata| 宏,其工作与 \cpp|__init| 相似,但它只初始化变量,% +而不是初始化函数。 -\cpp|__exit| 宏在模块被编译进内核时,引起省略该函数,并且如 \cpp|__init|,对于% -可加载的内核模块不产生效果。再次提示,当 cleanup 函数运行时,如果你考虑,这种情% -况更为合理;嵌入内核的驱动不需要一个 cleanup 函数,然而,可加载模块需要该函数。 +\cpp|__exit| 宏在模块被编译进内核时,引起省略该函数,并且如同 \cpp|__init|,对于% +可加载内核模块不产生效果。再次提示,当 cleanup 函数运行时,如果你想想,这种情% +况更为合理:嵌入内核驱动不需要一个 cleanup 函数,然而,可加载模块需要该函数。 -这些宏在 \src{include/linux/init.h} 文件中被定义,并负责来释放内核点用的内存。% -当你启动内核并看到如 Freeing unused kernel memory:236k free,这正是内核释入内% +这些宏在 \src{include/linux/init.h} 文件中被定义,并负责来释放内核占用的内存。% +当你启动内核并看到如 Freeing unused kernel memory:236k free,这正是内核释放内% 存的内容。 \samplec{examples/hello-3.c} -- 2.39.5