【问题标题】:Unknown symbol when compiling kernel module from multiple files从多个文件编译内核模块时出现未知符号
【发布时间】:2014-01-19 19:23:20
【问题描述】:

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

它在我的名为 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, ...);

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

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

谢谢, 罗伊。

【问题讨论】:

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


【解决方案1】:

在 Makefile 中尝试

obj-m += Module.o

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

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

【讨论】:

    【解决方案2】:

    回答: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, ...) 中的静态限制在其他文件中使用 LogMessage()。这个概念叫做static functions

    【讨论】:

    • StateMachine.c 不是一个单独的模块,它是一个源文件,可以(与 ModemAPI.c 一起)编译成一个单独的模块。
    • 首先,感谢您的帮助。其次,我尝试了您建议的makefile,问题仍然存在。警告:“LogMessage”[Base/Driver/Mymodule.ko] 未定义!
    【解决方案3】:

    我认为问题在于 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 是使用对象@ 构建的改为 987654324@。

    尝试重命名对象或您的 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

    【讨论】:

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

      【讨论】:

        猜你喜欢
        • 2020-09-30
        • 2013-05-18
        • 2012-02-26
        • 2021-11-28
        • 2020-09-11
        • 1970-01-01
        • 2012-11-08
        • 2011-07-15
        • 2012-08-06
        相关资源
        最近更新 更多