Linux内核驱动学习(三)----内核模块基础 | 设计 | 可选项

内核模块基础--特点及其命令使用

1、模块本身并不被编译进内核文件(zImage或bzImage)
2、可以根据需要在内核运行时动态加载、卸载----》进而达到节省空间的目的

命令详解(以下载驱动DNW为例):
insmod 模块名称(注意有.ko后缀)--安装
insmod dnw_usb.ko

lsmod-->查看安装的内核模块
技术分享

rmmod 模块名称(注意没有.ko后缀)---->卸载内核模块
技术分享
rmmod dnw_usb

内核模块设计--简单的模块编

技术分享
根据上图范例代码,比较应用程序代码的区别

与应用程序代码区别(主要涉及三个要素-->缺一不可)
1、引出内核模块的入口在哪里?(内核模块函数没有main函数)
  内核模块函数的入口是由宏module_init指明的,,其参数即是其函数入口。当使用insmod加载模块时,有宏module_init指定的初始化函数被调用。
2、出口(卸载函数)---宏module_exit指出。当使用rmmod卸载函数时,由module_exit指定的模块清除函数被调用。

3、头文件 #include<linux/init.h>   #include <linux/module.h>

注:应用程序由main函数指定程序入口。
除了以上使用module_init、module_exit指定初始化、卸载函数外。也可以给初始化函数与卸载函数取固定的名字:
初始化------>int init_module(void)
卸载函数---->void cleanup_module(void)

一、根据以上三要素编写简单的驱动
技术分享技术分享

二、编写该模块的Makefile。。(其格式较为固定)内容如下:
obj-m := helloworld.o //obi-m指明生成的内核模块名称
helloworld-objs := file1.o file2.o file3.o//多文件生成一个内核模块时的书写格式 ,
KDIR := /home/kindlyde/Desktop/arm-5/lesson3_3/linux-ok6410 //编译依赖的内核的路径
all:
         make -C ${KDIR} M=${PWD} modules ARCH=arm CROSS_COMPILE=arm-linux- //选项M代表需编译的内核模块的位置
rm:
         rm -f *.o *.ko *.order *.symvers



三、之后编译make;生成helloworld.ko文件,,把该文件放置到NFS文件系统中。。
技术分享
技术分享

四、挂载nfs文件系统之后,安装helloworld.ko内核模块
技术分享
技术分享

五、卸载helloworld内核模块
技术分享技术分享


内核模块可选项

1、模块声明

1.1MODULE_LICENSE(“遵守的协议”)----“GPL“、”GPL v2‘
申明该模块遵守的许可证协议
1.2MODULE_AUTHOR(“作者”)
申明模块的作者
1.3MODULE_DESCRIPTION(“模块的功能描述”)
申明模块的功能
1.4MODULE_VERSION(“v1.0”)
申明模块的版本
以申明模块遵守的协议为例:
声明之后安装该内核模块(不会出现 "module  license ‘unspecified‘ taints kernel"字样-->):
技术分享
技术分享

2、向内核模块的传入参数

主要通过宏module_param指定保存模块参数的变量;然后模块参数在加载模块时传递参数给模块
形式如下: module_param(name,type,perm)
参数:name: 变量的名称
           type:变量的类型,bool:布尔型 int:整型  charp:字符串型
            perm:访问权限。S_IRUGO:读权限  S_IWUSR:写权限

技术分享
技术分享
技术分享

3、符号导出

---->在不同内核模块之间实现函数调用
使用符号导出所使用的宏:(注意导出语句的位置,应在该变量定义之后。)
EXPORT_SYMBOL(符号名)
EXPORT_SYMBOL_GPL(符号名)
注:EXPORT_SYMBOL_GPL只能用于包含GPL许可证的模块

建立另一个add.c文件,在helloworld内核模块中实现调用
helloworld文件如下:
技术分享
技术分享

add.c文件如下:
技术分享技术分享


修改Makefile(生成两个独立的模块)
技术分享
技术分享
编译生成两个内核模块: helloworld.ko  和 add.ko
先安装add.ko驱动后安装helloworld.ko驱动。。调试出现以下结果,。。
技术分享
技术分享
技术分享



注--调试时遇到的错误

1、调试printk时未打印。
如下:画线的printk变量未打印。。
技术分享技术分享
技术分享
技术分享

制作的文件系统的关于日志消息的默认设置为 7 7 1 7:如下
技术分享
技术分享

这四个值是在kernel/printk.c 中被定义的,如下:

int console_printk[4] = {

               DEFAULT_CONSOLE_LOGLEVEL,/* console_loglevel */-->控制台日志级别

               DEFAULT_MESSAGE_LOGLEVEL,/* default_message_loglevel */--->默认消息日志级别

               MINIMUM_CONSOLE_LOGLEVEL,/* minimum_console_loglevel */-->最低控制台日志级别

               DEFAULT_CONSOLE_LOGLEVEL, /* default_console_loglevel */--->控制台默认优先级

};

以上关于四个数字的意义:

控制台日志级别:优先级高于该值的消息将被打印至控制台

默认的消息日志级别:将用该优先级来打印没有优先级的消息--->(即没有指定优先级的日志默认为优先级为7,,由上知等于控制台优先级。。则不打印消息。。)

最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级)

默认的控制台日志级别控制台日志级别的缺省值


更改默认消息级别低于7后。打印出消息;如下

技术分享技术分享

设置不同级别的日志的意义:

更好地控制不同级别的信息显示在控制台上,内核设置了控制台的日志级别console_loglevel。printk日志级别的作用是打印一定级别的消息,与之类似,控制台只显示一定级别的消息。


2、安装内核模块驱动时遇见如下错误:

技术分享

技术分享

原因:内核模块函数写错了。。缺少入口函数。。



郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。