Linux 内核链接

Linux Kernel Linking

因此,正如我在 here 中提到的,我正在对 Linux 内核进行一些更改。

现在,变化很小,但为了隔离它们,我希望我的东西在它自己的文件中。

我的更改基本上重新定义了一些函数,因此它们依赖于父文件中的函数。

所以foo.c包含:

/* headers.h does not contain a prototype my_fun2*/
#include "headers.h"
static void fun1(){
  ...
}

void fun2(){
 ...
 fun1()
}

并且my_foo.c包含:

/* headers.h does not contain a prototype my_fun2*/
#include "headers.h"
/* Note: I'm not #include "foo.c" */
extern void fun1();

void my_fun2()
{
  ...
  fun1()
}

您会注意到,在 my_foo.c 中我有 extern void fun1() 而不是 extern static void fun1(),因为这显然会因存储 类 而导致冲突。对此有进一步的解释就好了。

现在我已经有了我想要的代码,我将编辑相应的 Makefile 以具有以下内容

obj-$(CONFIG_MY_FOO) +=foo.o my_foo.o

虽然所有这些放在一起,但它似乎不起作用。我以前使用过制作文件,通常食谱是:

foo: foo.o bar.o
  $(cc) foo.o bar.o -o foo

foo.o: foo.c
  $(cc) -c foo.c

bar.o: bar.c
  $(cc) -c bar.c

然而,这似乎不是 Linux 内核 Makefile 中的格式。所以当我 运行 make 我得到以下错误:

my_foo.c:XX: undefined reference to `fun1()'

我错过了什么?我是否只需要将函数复制到 my_foo.c 因为 fun1() 是静态的?

在 C 中,全局函数默认具有外部链接,这意味着它们可以通过包含原型从其他编译单元(C 源文件)使用。

但是,如果函数被声明为static,则它变为内部链接,即只能在同一个编译单元中使用。

实际上,静态函数不会发出供链接器使用的符号,而非静态函数会发出这样的函数。

在头文件中将小型实用函数编写为静态函数是一种标准做法,还可以选择标记为 inline

如果函数不是很小,我的建议是将其设为外部(非静态)。请注意,在 Linux 内核中,为了能够从其他模块使用您的函数,您需要使用一些特定的宏来导出符号(不要混合使用 "kernel module" 和 "compilation unit")。