简体   繁体   English

Openwrt内核模块

[英]Openwrt kernel module

I'm learning how to develop a kernel module in Openwrt. 我正在学习如何在Openwrt中开发内核模块。 I make a hello world try. 我打个招呼世界。 The package directory tree is: 软件包目录树为:

khelloworld/

    Makefile

    src/

        khelloworld.c

        Makefile

The Openwrt Makefile source: 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))

The source Makefile: 源Makefile:

obj-m += khelloworld.o

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

The C helloworld source: 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" );
}

This module compiles well with this command: make package/khelloworld/compile 使用以下命令可以很好地编译该模块:make package / khelloworld / compile

Then I installed it in my openwrt using this command: 然后使用以下命令将其安装在openwrt中:

opkg install kmod-khelloworld-xxxxxx.ipk

and the install is done without errors. 并且安装完成没有错误。 but the problem dmesg doesn't display the expected message of the init function. 但是问题dmesg无法显示init函数的预期消息。

but it displays this message 但它显示此消息

[ 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 '

I thought that insmod is missing. 我以为insmod不见了。 So I added the following install macro to the Makefile just before "$(eval $(call KernelPackage,khelloworld))" 因此,我在"$(eval $(call KernelPackage,khelloworld))"之前将以下安装宏添加到Makefile中

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

but that didn't solve the problem. 但这并不能解决问题。 Has anyone an idea about this problem and how I can correct it? 有没有人知道这个问题,我该如何解决?

You are not having the init and exit statement in your load module. 您的加载模块中没有init和exit语句。

__init: macro causes the init function to be discarded and its memory freed once the init function finishes for built-in drivers, but not loadable modules __init:宏会导致初始化函数被丢弃,并且对于内置驱动程序(而非可加载的模块)而言,一旦初始化函数完成,其内存将被释放

__exit: macro causes the omission of the function when the module is built into the kernel, and like __exit. __exit:当模块内置到内核时,宏会导致函数的遗漏,就像__exit一样。

build in drivers only don't need the clean-up functions 内置驱动程序仅不需要清理功能

You can use modprobe to and remove the module from the Linux Kernel. 您可以使用modprobe来从Linux内核中删除该模块。


For example: 例如:

#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);

Insert/Remove the sample kernel module 插入/删除示例内核模块

# insmod hello.ko

# dmesg | tail -1
Hello world!

# rmmod hello.ko

# dmesg | tail -1
Cleaning up module.
  • Module is inserted into the kernel, the module_init macro will be invoked, which will call the function hello_init. 将模块插入内核后,将调用module_init宏,该宏将调用函数hello_init。

  • Module is removed with rmmod, module_exit macro will be invoked, which will call the hello_exit. 使用rmmod删除模块,将调用module_exit宏,该宏将调用hello_exit。 Using dmesg command, we can see the output from the sample Kernel module. 使用dmesg命令,我们可以看到示例内核模块的输出。


Additional information, 附加信息,

  1. For more information about building the Linux Load Module . 有关构建Linux Load Module的更多信息。

  2. Another information about debugging Linux Kernel Load Module using GDB . 有关使用GDB调试Linux内核加载模块的其他信息。

You have to make kernel version AND kernel features in your module compatible with kernel you want your module load into. 您必须使模块中的内核版本和内核功能与要加载模块的内核兼容。

As your version string doesn't have features SMP preempt , I think copying config of work kernel into your kernel-source/header tree should solve your problem. 由于您的版本字符串没有SMP preempt功能,因此我认为将工作内核的配置复制到您的kernel-source / header树中应该可以解决您的问题。 Like: 喜欢:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM