目录
驱动模块由三部分组成:
- 入口(安装):资源的申请
- 出口(卸载):资源的释放
- 许可证:GPL
1. 驱动模板
1.1. 在源码工程路径下创建.c文件
1.2. 编写驱动模板
//头文件支持
#include <linux/init.h>
#include <linux/module.h>
//static防止别人用重名函数
static int __init hello_init(void)//入口:资源申请
{
//_init将hello_init放到.init.text段中
return 0;
}
//static防止别人用重名函数
static void __exit hello_exit(void)//出口:资源释放
{
//_exit将hello_exit放到.exit.text段中
}
module_init(hello_init);//告诉内核驱动的入口地址
module_exit(hello_exit);//告诉内核驱动的出口地址
MODULE_LICENSE("GPL");//许可证
将文件保存到桌面上
1.3. 将模板放到ubuntu上
重点注意:此时的hello.c和任何工程都没关系是我们自己写的
作者将hello.c放在/home/hq/temp/demo下(非必须放到此处,自己决定)
1.4. 书写Makefile
KERNELDIR:=/lib/modules/$(shell uname -r)/build
#KERNELDIR:=/home/hq/temp/kernel-3.4.39/
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
clean:
make -C $(KERNELDIR) M=$(PWD) clean
obj-m:=hello.o
Makefile解析:
KERNELDIR:= b/modules/$(shell uname -r)ild/:这行代码定义了一个变量KERNELDIR,它指定了内核源代码的路径。它使用了uname -r命令来获取当前正在运行的内核的版本号,并将其与b/modules/路径拼接在一起。这样可以确保构建模块时使用正确的内核版本。
PWD:=$(shell pwd):这行代码定义了一个变量PWD,它表示当前目录的路径。pwd命令用于获取当前工作目录的路径,这样可以确保在构建模块时使用正确的路径。
all: :这是一个目标规则,表示默认目标。在这个规则下,它定义了要执行的命令。
make -C $(KERNELDIR) M=$(PWD) modules:这是all目标的命令。它使用make命令来构建内核模块。-C选项指定了内核源代码的路径,M选项指定了模块源代码的路径,modules表示构建模块。因此,这个命令告诉make在指定的内核源代码路径下构建模块。
clean: :这是另一个目标规则,用于清理构建过程中生成的文件。
make -C $(KERNELDIR) M=$(PWD) clean:这是clean目标的命令。它使用make命令来清理构建过程中生成的文件。与all目标类似,它使用-C选项指定了内核源代码的路径,M选项指定了模块源代码的路径,clean表示清理。
obj-m:=hello.o:这行代码定义了一个变量obj-m,它指定要构建的目标模块的名称为hello.o。在这个Makefile中,hello.o是一个示例模块的名称,你可以根据自己的需求修改它。
这个Makefile的作用是通过调用内核源代码中的Makefile来构建指定的内核模块。它通过设置正确的内核源代码路径和模块源代码路径,然后执行make命令来完成构建和清理操作。
1.5. 编译和安装
在hello.c和Makefile同级目录下执行make命令
得到下面文件
、
这个.ko后缀的文件是不是很熟悉?(在驱动移植篇)
我们查看Makefile
所以在ubuntu下安装就可
执行下面命令
sudo insmod hello.ko 安装命令
什么都没有发生,为什么?
拆卸命令sudo rmmod hello
2. printk
2.1. Source Insight查找命令
我们可以使用printk来进行测验
选中printk
按下ctrl+/
就能进入下面的查找页面
将使用例子放到printk处
2.2. printk讲解
2.2.1. 分析函数
printk和printf非常相似,只是多了一个打印级别
printk(KERN_ERR "SouthernBird\n")
在ubuntu下可以查看优先级别
cat /proc/sys/kernel/printk
2.2.2. 编写代码
//头文件支持
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
//static防止别人用重名函数
static int __init hello_init(void)//入口:资源申请
{
printk("SouthernBird\n");
//_init将hello_init放到.init.text段中
return 0;
}
//static防止别人用重名函数
static void __exit hello_exit(void)//出口:资源释放
{
printk("I am leave\n");
//_exit将hello_exit放到.exit.text段中
}
module_init(hello_init);//告诉内核驱动的入口地址
module_exit(hello_exit);//告诉内核驱动的出口地址
MODULE_LICENSE("GPL");//许可证
将代码放到ubuntu下重新编译(注makefile,目前不需要进行修改)
安装试验
我们可以看到什么都没打印,这是因为ubuntu开发人员将其屏蔽了
我们可以使用dmesg命令进行查看
2.3. 拓展
2.3.1. 关于printk函数测验用到的命令(掌握)
sudo insmod hello.ko 安装驱动模块
sudo rmmod hello 卸载驱动模块
lsmod 查看模块
dmesg 查看消息
sudo dmesg -C 直接清空消息不回显
sudo dmesg -c 回显后清空
2.3.2. 赋值知识点
= :赋值 需要等其他文件全部执行完,才执行调用的
:= :立即赋值
+= :附加赋值
?= :询问变量之前是否被赋值过,如果被赋值过本次赋值不成立
2.3.3. 打印级别的修改
》1.修改系统默认的级别
su root
echo 4 3 1 7 > /proc/sys/kernel/printk
》2.如果想修改开发板对应的打印级别
vi rootfs/etc/init.d/rcS
echo 4 3 1 7 > /proc/sys/kernel/printk