Kallel Omar
Kallel Omar

Reputation: 1218

Openwrt kernel module

I'm learning how to develop a kernel module in Openwrt. I make a hello world try. The package directory tree is:

khelloworld/

    Makefile

    src/

        khelloworld.c

        Makefile

The Openwrt Makefile source:

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:

obj-m += khelloworld.o

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

The C helloworld source:

#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

Then I installed it in my openwrt using this command:

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.

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. So I added the following install macro to the Makefile just before "$(eval $(call KernelPackage,khelloworld))"

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?

Upvotes: 2

Views: 6168

Answers (2)

MrCryo
MrCryo

Reputation: 681

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. Like:

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

Upvotes: 2

danglingpointer
danglingpointer

Reputation: 4920

You are not having the init and exit statement in your load module.

__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

__exit: macro causes the omission of the function when the module is built into the kernel, and like __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.


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 is removed with rmmod, module_exit macro will be invoked, which will call the hello_exit. Using dmesg command, we can see the output from the sample Kernel module.


Additional information,

  1. For more information about building the Linux Load Module.

  2. Another information about debugging Linux Kernel Load Module using GDB.

Upvotes: 3

Related Questions