从多个文件编译内核模块时的未知符号

时间:2014-01-02 10:57:28

标签: makefile linux-kernel kernel linux-device-driver kernel-module

我正在编写一个由几个源文件组成的内核模块, 其中一个源文件具有需要由同一模块中的其他对象使用的函数。

它在我的名为ModemAPI.c的文件中定义

static void LogMessage ( char *format, ...)

这个c文件应该(和其他文件一起)编译成一个内核模块,其makefile如下所示:

obj-m += ModemAPI.o

ModemAPI-objs := ../Common/StateMachine.o ../Common/ElementsPool.o 

当我编译这个内核模块时,我在链接期间得到一个警告,上面的函数“LogMessage”是未定义的,当我尝试加载模块时,我得到一个错误,说它里面有一个未知的符号(当然是LogMessage)

编辑:为了弄清楚,函数“LogMessage”在文件ModemAPI.c中声明并实现,而且它通过EXPORT_SYMBOL导出

EXPORT_SYMBOL(LogMessage);

在使用该函数的文件(例如StateMachine.c)中,它是通过extern声明的

extern void LogMessage ( char *format, ...);

模块编译,问题处于链接阶段。

有没有人知道这可能是什么问题?

谢谢, 罗伊。

4 个答案:

答案 0 :(得分:0)

回答:moreover it is exported via EXPORT_SYMBOL

EXPORT_SYMBOL()使LogMessage()可供可加载内核模块访问。

例如,导出vmalloc()以在内核模块http://lxr.free-electrons.com/source/mm/vmalloc.c#L1708

中使用

但是你仍然需要在可加载内核模块源中包含vmalloc.h。所以不要与extern和EXPORT_SYMBOL混淆。

<强>解决方案

在Makefile中,修改如下

obj-m += ModemAPI.c StateMachine.c

即应首先编译具有LogMessage()的ModemAPI.c。

建议更改为Makefile

obj-m += Mymodule.o

Mymodule-objs := ../Common/ModemAPI.o ../Common/StateMachine.o ../Common/ElementsPool.o 

编辑:2

static void LogMessage ( char *format, ...)中的

static限制在其他文件中使用LogMessage()。这个概念称为static functions

答案 1 :(得分:0)

在Makefile中尝试

obj-m += Module.o

Module-objs :=  ../Common/StateMachine.o ../Common/ElementsPool.o ../Common/ModemAPI.o

有时候.o文件的顺序很重要

答案 2 :(得分:0)

我认为问题是ModemAPI.c没有被编译。

  

obj-m + = ModemAPI.o
  ModemAPI-objs:= ../Common/StateMachine.o ../Common/ElementsPool.o

通常obj-m += ModemAPI.o告诉make使用ModemAPI.c(我认为这是linux make系统的默认设置),但添加ModemAPI-objs会告诉make ModemAPI.o是使用对象../Common/StateMachine.o ../Common/ElementsPool.o构建的。

尝试重命名对象或您的ModemAPI.c文件:

 obj-m += modem.o #something not named ModemAPI.o
 ModemAPI-objs := ModemAPI.o ../Common/StateMachine.o ../Common/ElementsPool.o 

 obj-m += ModemAPI.o 
 ModemAPI-objs := main.o ../Common/StateMachine.o ../Common/ElementsPool.o 

其中ModemAPI.c已重命名为main.c

答案 3 :(得分:0)

  1. 确保您的内核编译时支持模块加载(例如,如果/proc/modules存在,您可以确定,它是)
  2. 确保您正在针对尝试加载模块的同一内核进行编译
  3. 定义obj-m + = ...和[my-module-ko]-objs:= [所有xx.o对象列表]