【问题标题】:Openwrt kernel moduleOpenwrt 内核模块
【发布时间】:2017-10-06 10:53:39
【问题描述】:

我正在学习如何在 Openwrt 中开发内核模块。我试着打个招呼。包目录树为:

khelloworld/

    Makefile

    src/

        khelloworld.c

        Makefile

Openwrt Makefile 源代码:

include $(TOPDIR)/rules.mk
include $(INCLUDE_DIR)/kernel.mk

PKG_NAME:=khelloworld
PKG_RELEASE:=1
PKG_VERSION:=1.0

include $(INCLUDE_DIR)/package.mk

define KernelPackage/khelloworld
  SUBMENU:=HELLO WORLD MODULES
  TITLE:=khelloworld
  MAINTAINER:=Nobody
  MENU:=1
  FILES:=$(PKG_BUILD_DIR)/$(PKG_NAME).$(LINUX_KMOD_SUFFIX)
endef

EXTRA_KCONFIG:= \
    CONFIG_HELLO_MOD=m

EXTRA_CFLAGS:= \
    $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=m,%,$(filter %=m,$(EXTRA_KCONFIG)))) \
    $(patsubst CONFIG_%, -DCONFIG_%=1, $(patsubst %=y,%,$(filter %=y,$(EXTRA_KCONFIG)))) \

#MAKE_OPTS:= \
#   EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
#   $(EXTRA_KCONFIG)

define Build/Prepare
    # Copy sources
    mkdir -p $(PKG_BUILD_DIR)
    cp -R ./src/* $(PKG_BUILD_DIR)/
endef

define Build/Compile
    $(MAKE) -C "$(LINUX_DIR)" \
        CROSS_COMPILE="$(TARGET_CROSS)" \
        ARCH="$(LINUX_KARCH)" \
        SUBDIRS="$(PKG_BUILD_DIR)" \
        EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
        $(EXTRA_KCONFIG) \
        modules
endef
$(eval $(call KernelPackage,khelloworld))

源 Makefile:

obj-m += khelloworld.o

all:
    $(MAKE) -C "$(LINUX_DIR)" \
    $(MAKE_OPTS) \
    modules

C helloworld 源码:

#include <linux/module.h>
#include <linux/kernel.h>

int init_module( void ) {
    printk( KERN_INFO "Hello World KERNEL!!!\n" );
    return 0;
}

void cleanup_module( void ) {
    printk( KERN_INFO "Goodbye World KERNEL!!!\n" );
}

这个模块用这个命令编译得很好:make package/khelloworld/compile

然后我使用以下命令将它安装在我的 openwrt 中:

opkg install kmod-khelloworld-xxxxxx.ipk

并且安装完成没有错误。但问题dmesg 没有显示初始化函数的预期消息。

但它会显示此消息

[ 9493.863000] khelloworld: version magic '3.4.11-rt19 mod_unload modversions MIPS32_R1 32BIT ' should be '3.4.11-rt19 SMP preempt mod_unload MIPS32_R1 32BIT '

我以为insmod 不见了。所以我在 "$(eval $(call KernelPackage,khelloworld))" 之前的 Makefile 中添加了以下安装宏

define Build/install
    insmod $(PKG_BUILD_DIR)/khelloworld.ko
endef

但这并没有解决问题。 有没有人知道这个问题以及如何纠正它?

【问题讨论】:

  • 您缺少 init 和 exit 语句。你试过吗?
  • @LethalProgrammer 不能解决问题
  • 你添加了你使用 modprobe 加载的模块吗?
  • 我的代码在带有 insmod 的 ubuntu 中运行良好。但问题是我想在openwrt上运行它。我不知道该怎么做

标签: c linux makefile kernel-module openwrt


【解决方案1】:

您的加载模块中没有 init 和 exit 语句。

__init: 宏会导致 init 函数被丢弃并在 init 函数完成后释放其内存以用于内置驱动程序,但不可加载模块

__exit:宏导致模块内置内核时函数的省略,和__exit一样。

仅内置驱动程序不需要清理功能

您可以使用modprobe 将模块从 Linux 内核中删除。


例如:

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>     /* Needed for the macros */

int __init hello_init( void ) {
    printk( KERN_INFO "Hello World KERNEL!!!\n" );
    return 0;
}

void __exit hello_exit( void ) {
    printk( KERN_INFO "Goodbye World KERNEL!!!\n" );
}}

module_init(hello_2_init);
module_exit(hello_2_exit);

插入/删除示例内核模块

# insmod hello.ko

# dmesg | tail -1
Hello world!

# rmmod hello.ko

# dmesg | tail -1
Cleaning up module.
  • 模块被插入内核,会调用module_init宏,调用函数hello_init。

  • 使用 rmmod 删除模块,将调用 module_exit 宏,该宏将调用 hello_exit。使用 dmesg 命令,我们可以看到示例内核模块的输出。


其他信息,

  1. 有关构建Linux Load Module 的更多信息。

  2. 关于调试的其他信息Linux Kernel Load Module using GDB

【讨论】:

    【解决方案2】:

    您必须使模块中的内核版本和内核功能与您希望模块加载到的内核兼容。

    由于您的版本字符串没有功能SMP preempt,我认为将工作内核的配置复制到您的内核源/头文件树中应该可以解决您的问题。喜欢:

    cp /boot/config-`uname -r` /usr/src/linux-`uname -r`/.config
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-04-11
      • 2013-12-17
      • 1970-01-01
      • 2018-03-06
      • 2014-03-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      相关资源
      最近更新 更多