测试模块常用的命令:
(1) lsmod (list module,将模块列表显示 ) 功能是打印出当前内核中已经安装的模块列表。
(2) insmod(install module,安装模块 ) 功能是向当前内核中去安装一个模块, 用法是
insmod xxx.ko
(3) modinfo (module information, 模块信息) 功能是打印出一个内核模块的自带信息。
用法是 modinfo xxx.ko
(4) rmmod(remove module, 卸载模块) , 功能是从当前内核中卸载一个已经安装了的模块
用法是 rmmod xxx(注意卸载模块时只需要输入模块名即可, 不能加.ko 后缀)
关于 函数修饰符和关键字 __init,__exit和static
__init和__exit本质上是个宏定义
__init 的作用就是将被他修饰的函数放入.init.text 段中去(本来默认情况下函数是被放入.text 段中)
__exit的作用就是将被他修饰的函数放入.exit.text 段中去(本来默认情况下函数是被放入.text 段中)
整个内核中的所有的这类函数都会被链接链器接放入.init.text 段中, 所以所有的内核模块的__init 修饰的函数其实是被统一放在一起的。 内核启动时统一会加载.init.text 段中的这些模块安装函数, 加载完后就会把这个段给释放掉以节省内存。
static的作用:
- 静态函数只能在声明它的文件中可见,其他文件不能引用该函数
- 不同的文件可以使用相同名字的静态函数,互不影响
printkk 在内核源码中用来打印信息的函数
printk 是 linux 内核源代码中自己封装出来的一个打印函数, 是内核源码中的一个普通函数, 只能在内核源码范围内使用, 不能在应用编程中使用,
printk 的打印级别是用来控制 printk 打印的这条信息是否在终端上显示的,在内核中的打印级别为0~7 ,默认打印的级别为4
使用命令cat /proc/sys/kernel/printk
4 4 1 7
(1)第一个参数 4表示小于4优先级消息才会被输出到控制台。
(2)第二个参数4 表示默认的printk消息优先级别,(数字越小优先级越高)
(3)第三个参数1 表示可接收的最高优先级,。
(4)第四个参数7 默认控制台优先级,即第一个参数的默认优先级。
echo 7 4 1 7 > /proc/sys/kernel/printk (4>7)所以可以把打印信息显示在终端上,
注意:在内核中写的printk打印语句是直接看不到的,需要把 echo 7 4 1 7 > /proc/sys/kernel/printk 放到根文件的
etc/init.d/rcS中,启动应用程序的时候默认打印级别大于控制终端的级别
\
Makefile 分析:
KERNELDIR= /lib/modules/$(shell uname -r)/build/
#KERNELDIR:= /home/linux/kernel/kernel-3.4.39/
PWD=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=six_drv.o
#内核版本号
KERN_VER = $(shell uname -r)
#用来编译这个模块的内核源码树的目录,
KERN_DIR = /lib/modules/$(KERN_VER)/build
# 开发板的 linux 内核的源码树目录 这是我的内核源码树目录
KERNELDIR:= /home/linux/kernel/kernel-3.4.39/
#把 module_test.c 添加到编译目标中去, -m 表示把它编译成一个模块
obj-m+= six_drv.o
#目标: 这个命令用来编译实际的模块, make 执行的命令, ·pwd·表示我们要把 pwd 当命令去执行, M=`pwd`表示我们
进入到当前这个目录下编译完成后还能回来(记录当前目录) 。 modules 表示内核中的目标, 然后内核中的目标负责对
我们的程序进行编译。
make -C $(KERN_DIR) M=`pwd` modules 这个命令用来实际编译模块, 工作原理就是:利用 make -C 进入到我们指定的内核源码树目录下, 然后在源码目录树下借用内核源码中定义的模块编译规则去编译这个模块, 编译完成后把生成的文件还拷贝到当前目录下, 完成编译.