- 论坛徽章:
- 0
|
模块就是能用命令进行加载到内核或从内核卸载的程序,它们可以使机器在不重启的情况下可以扩展内核功能,其中一种模块类型就是驱动,可以用lsmod命令来查看什么模块已经被加进内核。
当内核需要一个不是驻留在内核里的模块时,它会执行modprobe命令去把模块加载上,而传递给modprobe命令的参数有两种形式,如char-major-180-*
usbcore,该种形式定义在/etc/modprobe.d/aliases中,对应的模块名为usbcore.ko,然后modprobe将去查看一下/lib/modules/version/modules.dep看是否有模块必须在加载该模块之前加载,该文件是由depmod
-a命令生成的,是关于模块依赖性的,最后modprobe用insmod命令把依赖的模块加载上,再把该模块加载上。
在内核2.3.13之前,内核模块必须有两个功能:初始化功能(init_module()),它是当模块被加载到内核时调用的;卸载功能(cleanup_module()),它是当模块被卸载之前调用的。现在可以用任何名字来实现一个模块的初始化或卸载,但每一个内核模块都必须包含linux/module.h
如果你要用到一些宏扩展如prink(),还需要包含linux/kernel.h。
简单模块例子:
hello.c
#include
#include
#include
MODULE_LICENSE("Dual
BSC/GPL");
MODULE_AUTHOR("Sam
Shen ");
MODULE_DESCRIPTION("Test
Module Program");
MODULE_SUPPORTED_DEVICE("Hello,world");
static
int _ _init hello_init(void)
{
printk(KERN_ALERT"Hello,
world!\n");
return
0;
}
static
void _ _exit hello_exit(void)
{
printk(KERN_ALERT"Goodbye,
cruel world!\n");
}
module_init(hello_init);
module_exit(hello_exit);
Makefile
obj-m
+= hello.o
KERNELDIR:=/lib/modules/$(shell
uname -r)/build
PWD=$(shell
pwd)
all:
make
-C $(KERNELDIR) M=$(PWD) modules
clean:
make
-C $(KERNELDIR) M=$(PWD) clean
(想了解更多关于编译模块,请查看linux/Documentation/kbuild/modules.txt,更多关于内核模块的Makefile,请查看linux/Documentation/kbuild/makefiles.txt)
_
_ init声明是当init函数执行完成后内核能够回收空间,_
_initdata和它有相同的功能,但是是对于变量而不是函数的,
_
_exit声明是为了内核能够省略掉cleanup函数,它们可装载模块不受影响。MODULE_*定义在linux/include/linux/module.h,它们不被内核本身使用,只是为了让一些工具查看模块的信息。
按Ctrl+Alt+F5,进入tty5,用modinfo
hello.ko查看模块的信息,用sudo
insmod hello.ko加载模块,用lsmod
| grep hello查看模块是否已加载上,用sudo
rmmod
hello卸载该模块。所有已经加载的模块都列在文件/proc/modules中,故也可以通过查看hello是否出现在该文件中来判断模块是否已经加载上,一般刚加载的模块加在第一行,如:hello
2432 0 - Live 0xf8974000
(P),其中hello为模块名,2432是模块大小,0是使用数目,-Live是模块状态,0xf8974000是模块位置,(P)为非标准内核模块。
可以给模块传递命令行参数,但不是用argc/argv的机制,而是用module_param()或module_param_array()宏,它们定义在include/linux/moduleparam.h文件中,使用范例:
hello.c
#include
#include
#include
#include
#include
MODULE_LICENSE("Dual
BSC/GPL");
MODULE_AUTHOR("Sam
Shen ");
MODULE_DESCRIPTION("Test
Module Program");
MODULE_SUPPORTED_DEVICE("Hello,world");
static
short int myshort = 1;
static
int myint = 2;
static
long int mylong = 8888;
static
char *mystring = "shenxiaocheng";
static
int myintArray[2] = {-1, 1};
static
int arr_argc = 0;
module_param(myshort,
short, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
MODULE_PARM_DESC(myshort,
"A short integer");
module_param(myint,
int, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
MODULE_PARM_DESC(myint,
"An integer");
module_param(mylong,
long, S_IRUSR);
MODULE_PARM_DESC(mylong,
"A long integer");
module_param(mystring,
charp, 0000);
MODULE_PARM_DESC(mystring,
"A character string");
module_param_array(myintArray,
int, &arr_argc,0000);
MODULE_PARM_DESC(myintArray,
"An array of integer");
static
int __init hello_init(void)
{
int
i;
printk(KERN_ALERT"Hello,
world!\n");
printk(KERN_ALERT"myshort
is a short interger: %hd\n",myshort);
printk(KERN_ALERT"myint
is an integer %d\n", myint);
printk(KERN_ALERT"mylong
is a long integer: %ld\n",mylong);
printk(KERN_ALERT"mystring
is a string: %s\n", mystring);
for(i=0;
i
printk(KERN_ALERT"myintArray[%d]
= %d\n", i, myintArray);
printk(KERN_ALERT"got
%d argumeters for myintArray.\n", arr_argc);
return
0;
}
static
void __exit hello_exit(void)
{
printk(KERN_ALERT"Goodbye,
cruel world!\n");
}
module_init(hello_init);
module_exit(hello_exit);
加载时,可以用sudo
insmod hello.ko myshort=5命令为模块传递参数。
如果我们把hello_init和hello_exit函数分开放在start.c和stop.c文件中,则Makefile需要改为
obj-m
+= startstop.o
startstop-objs
:= start.o stop.o
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/78437/showart_1355559.html |
|