Eudyptula挑战和内核路径

use*_*276 10 makefile linux-kernel eudyptula-challenge

我决定参加Eudyptula挑战赛.在我提交了第一个任务之后,就是构建一个简单的"Hello World!" 模块,我收到了以下答案.

请阅读Makefile的要求,并允许根据文件系统上的任何内核源代码树构建模块,而不仅仅是那些/lib/在某个时间点安装的内核.

要求是:

Makefile应该能够针对当前运行的内核的源构建内核模块,并且能够从环境变量接受任意内核源目录.

我正在做的是检查是否KERNELRELEASE设置了环境变量.如果是我构建模块

$(KERNELRELEASE)/build  
Run Code Online (Sandbox Code Playgroud)

如果它不反对

/lib/modules/$(shell uname -r)/build
Run Code Online (Sandbox Code Playgroud)

我无法理解为什么这不能满足这项任务的要求.

Sam*_*nko 26

根据Eudyptula挑战规则,禁止直接提供解决方案,因此我将尝试描述答案元素,以便您自己提出解决方案.基本上,我在下面编写的所有内容都在Documentation/kbuild/modules.txt文件中进行了描述(特别是在3.1节 - 共享Makefile中),所以我认为这不会是某种违反规则的行为.以下是对上述文档中描述内容的解释.

KERNELRELEASE 变量

您错误的是认为这$(KERNELRELEASE)是为了保持内核的路径.$(KERNELRELEASE)变量实际意味着什么- 您可以在Documentation/kbuild/makefiles.txt中找到它:

KERNELRELEASE

$(KERNELRELEASE)是一个单独的字符串"2.4.0-pre4",适用于构造安装目录名称或显示在版本字符串中.有些拱门Makefiles将它用于此目的.

关键是,你Makefile将要执行2次:从您的 make命令和内核 Makefile.并且$(KERNELRELEASE)可以帮助解决这个问题:

  1. 如果未定义此变量,则表示您Makefile正在运行make命令; 在这一步,你将执行内核Makefile(使用-Cparam 提供内核目录).一旦你运行make了内核的Makefile(来自你的Makefile 里面),你Makefile将被第二次执行(见下一项).
  2. 如果定义了这个变量,那么你Makefile正在从内核执行Makefile(它定义了这个变量并调用了你的Makefile后面).在此步骤中,您可以使用内核构建系统功能,例如obj-m.

-C PARAM

你真正需要做的是在你的Makefile内容中定义一些自定义变量,它将保存内核目录路径.你可以称它为KDIR例.如您所知,您的内核源位于此路径:/lib/modules/$(shell uname -r)/build.接下来,您可以在执行内核的Makefile时将此变量提供给-Cparam(请参阅man 1 make).

接下来,您必须能够从您的外部传递此变量Makefile.为此,可以使用条件变量赋值运算符:

KDIR ?= /lib/modules/$(shell uname -r)/build
Run Code Online (Sandbox Code Playgroud)

这样,如果将KDIR变量传递给Makefile,如下所示:

$ make KDIR=bla-bla-bla
Run Code Online (Sandbox Code Playgroud)

KDIR变量将你传递的值.否则它将包含默认值,即/lib/modules/$(shell uname -r)/build.