模块编程
模块init&exit 宏
- module_init 在初始化或模块insert时调用, 定义模块入口函数
/**
* module_init() - driver initialization entry point
* @x: function to be run at kernel boot time or module insertion
*
* module_init() will either be called during do_initcalls() (if
* builtin) or at module insertion time (if a module). There can only
* be one per module.
*/
#define module_init(x) __initcall(x);
- module_exit模块退出时调用, 定义模块退出时的清理函数
/**
* module_exit() - driver exit entry point
* @x: function to be run when driver is removed
*
* module_exit() will wrap the driver clean-up code
* with cleanup_module() when used with rmmod when
* the driver is a module. If the driver is statically
* compiled into the kernel, module_exit() has no effect.
* There can only be one per module.
*/
#define module_exit(x) __exitcall(x);
Licensing and Module Documentation
- MODULE_LICENSE 通过license可以提醒用户模块是否开源
/*
* The following license idents are currently accepted as indicating free
* software modules
*
* "GPL" [GNU Public License v2 or later]
* "GPL v2" [GNU Public License v2]
* "GPL and additional rights" [GNU Public License v2 rights and more]
* "Dual BSD/GPL" [GNU Public License v2
* or BSD license choice]
* "Dual MIT/GPL" [GNU Public License v2
* or MIT license choice]
* "Dual MPL/GPL" [GNU Public License v2
* or Mozilla license choice]
*
* The following other idents are available
*
* "Proprietary" [Non free products]
*
* There are dual licensed components, but when running with Linux it is the
* GPL that is relevant so this is a non issue. Similarly LGPL linked with GPL
* is a GPL combined work.
*
* This exists for several reasons
* 1. So modinfo can show license info for users wanting to vet their setup
* is free
* 2. So the community can ignore bug reports including proprietary modules
* 3. So vendors can do likewise based on their own policies
*/
#define MODULE_LICENSE(_license) MODULE_INFO(license, _license)
- MODULE_AUTHOR 模块作者,不被内核使用,只用于查看
- MODULE_DESCRIPTION 模块描述,不被内核使用,只用于查看
- MODULE_SUPPORTED_DEVICE 支持的设备,不被内核使用,只用于查看
模块代码
#include <linux/module.h> /* Needed by all modules */
#include <linux/kernel.h> /* Needed for KERN_INFO */
#include <linux/init.h> /* Needed for the macros */
#include <linux/moduleparam.h> /* Needed for the params */
/*
* int
*/
static int cnt = 0;
module_param(cnt, int, 0);
MODULE_PARM_DESC(cnt, " is int param");
/*
* string
*/
static char *str = "lxhuster";
module_param(str, charp, 0);
MODULE_PARM_DESC(str, " is str param");
/*
* buf
*/
static char name[100] = {0};
module_param_string(myname, name, 100, 0);
MODULE_PARM_DESC(name, " is str param");
/*
* int array
*/
static int arry[2] = {0};
static unsigned int num = 2;
module_param_array(arry, int, &num, 0);
MODULE_PARM_DESC(arry, " is arry param");
/*
* 模块入口函数
*/
static int __init hello_init(void)
{
printk(KERN_ALERT "hello world!\r\n");
printk(KERN_ALERT "cnt is %d \r\n", cnt);
printk(KERN_ALERT "str is %s \r\n", str);
printk(KERN_ALERT "name is %s \r\n", name);
printk(KERN_ALERT "arry[0] is %d arry[1] is %d\r\n", arry[0], arry[1]);
return 0;
}
/*
* 模块清理函数
*/
static void __exit hello_cleanup(void)
{
printk(KERN_ALERT "good to go world\r\n");
}
module_init(hello_init);
module_exit(hello_cleanup);
MODULE_LICENSE("GPL");
/*
* 不被内核使用
*/
MODULE_AUTHOR("lxhuster"); // 模块作者
MODULE_DESCRIPTION("module hello"); // 模块描述
MODULE_SUPPORTED_DEVICE("x86"); // 支持的设备
编译模块
# KERNELRELEASE被定义表明被内核构造系统调用
ifneq ($(KERNELRELEASE), )
obj-m := hello.o
# else表明从命令行调用
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
all:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
clean:
rm -rf *.cmd *.o *.ko *.mod.c
endif
- 模块装卸命令
sudo insmod hello.ko cnt=10 str="dash" myname="Thestars,mydestination" arry=5,6
sudo rmmod hello.ko
- printk打印
dmesg
- 模块信息
sudo modinfo hello.ko
- 查看内核导出的符号
cat /proc/kallsyms