Linux Driver 入门 - hello world - 动态模块加载与卸载

Abstract

  1. Coding and compile a simple dynamic driver module - HelloWorld
  2. loading module and unloading module
  3. dmesg
  4. Kernel symbol table

Create a Simple Dynamic Driver Module - HelloWorld

hello.c

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

MODULE_LICENSE("Dual BSD/GPL");
static
int hello_init(void) { printk(KERN_ALERT "TEST: hello world, this is hello world module\n"); return 0; } static void hello_exit(void) { printk(KERN_ALERT "TEST: Good bye, from hello world module\n"); } module_init(hello_init); module_exit(hello_exit);

 

> #include <linux/init.h>

This header contains the definition of the functions used in this module.

> module_init() is a macro which defines the function to be called at module insertion time or at system boot time.

> module_exit() is a macro which defines the function to be called at module removal time. This function is also called clean up function

> Kernel modules must always contain these two functions: init_module and cleanup_module

> #include <linux/module.h>

This header is included to add support for Dynamic loading of the module into the Kernel.

A special macro like MODULE_LICENSE is defined in this header.

MODULE_LICENSE

This macro is used to tell the kernel that this module bears a free license; without such a declaration, the kernel complains when the module is loaded.

> printk

int printk(const char *fmt, ...);

 

printk(KERN_DEBUG "Debug message shown!\n");

 

Different Loglevels, along with their numerical values, are shown here:

 

0 KERN_EMERG Emergency condition, system is probably dead
1 KERN_ALERT Some problem has occurred, immediate attention is needed
2 KERN_CRIT A critical condition
3 KERN_ERR An error has occurred
4 KERN_WARNING A warning
5 KERN_NOTICE Normal message to take note of
6 KERN_INFO Some information
7 KERN_DEBUG Debug information related to the program

 

MakeFile Version 1

This can tell you which header file you need in Makefile:

obj-m +=hello.o

KDIR=/usr/src/linux-headers-$(shell uname -r)
 all: $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules clean: rm -rf *.o *.ko *.mod *.syvers *.order

 > "-C" option tells make command to switch to $(KDIR) which is kernel directory

MakeFile Version 2

obj-m :=hello.o

KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)

all:
    $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules

clean:
    rm -rf *.o *.ko *.mod *.syvers *.order

 

 

yubao@yubao-ThinkPad-E560:~$ uname  -r
4.13.0-36-generic

 

 Compiling the Module

Make

yubao@yubao-ThinkPad-E560:~/Documents/LinuxStudy$ make
make -C /usr/src/linux-headers-4.13.0-36-generic SUBDIRS=/home/yubao/Documents/LinuxStudy modules
make[1]: Entering directory '/usr/src/linux-headers-4.13.0-36-generic'
  CC [M]  /home/yubao/Documents/LinuxStudy/hello.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/yubao/Documents/LinuxStudy/hello.mod.o
  LD [M]  /home/yubao/Documents/LinuxStudy/hello.ko
make[1]: Leaving directory '/usr/src/linux-headers-4.13.0-36-generic'
yubao@yubao-ThinkPad-E560:~/Documents/LinuxStudy$ ls
hello.c  hello.ko  hello.mod.c  hello.mod.o  hello.o  Makefile  modules.order  Module.symvers

 

Loading Kernel Modules

Two Kernel Utilities to load the modules:

insmod
> modprobe

insmod

> Insmod is a kernel utility that installs loadable Kernal modules into the kernel.

> It actually loads the module code and data into the Kernal land, links any unresolved symbols in the module to the symbol table of the Kernal.

> Insmod accepts a number of command line options and it can assign a value to parameters in a module before linking it to the current kernel.

> Note that if a module is correctly designed, it can be configured at load time by passing arguments to insmod.

 

yubao@yubao-ThinkPad-E560:~/Documents/LinuxStudy$ sudo insmod hello.ko
[sudo] password for yubao:

 modprobe

> It's a Linux utility which offers more features than basic insmod

> It has the ability to decide which modules to load /lib/modules/$(uname -r)

> Its aware of module dependencies

> It supports resolution of recursive module dependencies

 

I encountered this error:

yubao@yubao-ThinkPad-E560:/lib/modules/4.13.0-36-generic$ sudo modprobe  hello
modprobe: FATAL: Module hello not found in directory /lib/modules/4.13.0-36-generic

 

The reason is that modprobe looks into /lib/modules/$(uname -r) for the modules and therefore won't work with local file path. That's one of differences between modprobe and insmod.

Therefore:

$ dmesg -c

yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ sudo cp hello.ko /lib/modules/4 .13.0-36-generic/extra/
yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ sudo depmod
yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ sudo modprobe hello
yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ dmesg

dmsg

dmseg -c : clear history

[ 6384.761442] TEST: hello world, this is hello world module

 

Remove Module

> rmmod

yubao@yubao-ThinkPad-E560:~/Documents/LinuxStudy$ sudo rmmod hello.ko

 >Modprobe

$modprobe -r module-name

yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ sudo modprobe -r hello
yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/HelloWorld$ dmesg
[15909.539018] TEST: Good bye, from hello world module

 How to debug symbol error?

Sample code with Symbol Undefine Error:

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

//Just declared
extern int g_value;

static int hello_init(void)
{
  printk(KERN_ALERT "TEST: hello world, this is hello world module\n");
  printk("Hello world!!. Value of g_value is %d \n",g_value);
  return 0;
}

static void hello_exit(void)
{
  printk(KERN_ALERT "TEST: Good bye, from hello world module\n");
}

module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("yubao");
MODULE_DESCRIPTION("Kernal Sybmol Table");

 

Makefile

obj-m +=hello.o

all:
    make -C /lib/modules/$(shell uname -r)/build  M=$(PWD) modules

clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

 

Error description:

yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/SybolError$ sudo insmod hello.ko
[sudo] password for yubao:
insmod: ERROR: could not insert module hello.ko: Unknown symbol in module

 

 Use "nm" to debug

yubao@yubao-ThinkPad-E560:~/MyProjects/Linux/driver/SybolError$ nm hello.ko
0000000000000030 T cleanup_module
                 U __fentry__
                 U g_value
0000000000000030 t hello_exit
0000000000000000 t hello_init
0000000000000000 T init_module
0000000000000068 r __module_depends
                 U printk
0000000000000000 D __this_module
0000000000000020 r __UNIQUE_ID_author9
0000000000000000 r __UNIQUE_ID_description10
000000000000002d r __UNIQUE_ID_license8
0000000000000071 r __UNIQUE_ID_name9
0000000000000040 r __UNIQUE_ID_srcversion10
000000000000007c r __UNIQUE_ID_vermagic8

 

 How to solve this problem?

Replace "extern int g_value;" with "extern int g_value;". Then "make clean &make".

Is it mandatory to export your module symbols?

yes

> "static" - visible only within their own source file

> "external" - potentially visible to any other code built into the kernel itself

>"exported" - visible and available to any loadable module

 

 

 

 

 

 

posted on 2018-03-09 19:43  LiuYubao  阅读(415)  评论(0编辑  收藏  举报

导航