我正在学习如何在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
没有显示init函数的预期消息。
但它会显示此消息
[ 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))"
define Build/install
insmod $(PKG_BUILD_DIR)/khelloworld.ko
endef
但这并没有解决问题。 有没有人对这个问题有所了解以及如何纠正它?
答案 0 :(得分:2)
您的加载模块中没有init和exit语句。
__ init:宏导致init函数被丢弃,内存驱动程序的init函数完成后释放内存,但不能加载模块
__ exit:当模块内置到内核中时,宏会导致省略函数,就像__exit一样。
内置驱动程序只需要不需要清理功能
您可以使用appIE.document.getElementbyid("pickup-date").Value = Format(Date, "12/20/17")
从Linux内核中删除该模块。
例如:
modprobe
插入/删除示例内核模块
#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);
将模块插入内核,调用module_init宏,调用函数hello_init。
使用rmmod删除模块,将调用module_exit宏,这将调用hello_exit。使用dmesg命令,我们可以看到示例内核模块的输出。
其他信息,
有关构建Linux Load Module。
答案 1 :(得分:2)
您必须在模块中创建与您希望模块加载的内核兼容的内核版本和内核功能。
由于您的版本字符串没有功能SMP preempt
,我认为将工作内核的配置复制到您的kernel-source / header树应该可以解决您的问题。像:
cp /boot/config-`uname -r` /usr/src/linux-`uname -r`/.config