目录
1、驱动的概念
驱动:驱动就是计算机程序访问硬件的一个接口(API),这个接口由操作系统提供,作为操作系统涉及到安全管理机制,应用层不能够直接访问硬件,需要通过驱动函数接口来访问硬件。
2、linux驱动的种类
驱动的种类:字符设备驱动、块设备驱动、网卡设备驱动
字符驱动设备:按照字节流来访问,只能顺序访问设备。例如:鼠标、键盘、串口、LED等
块设备驱动:按照block(512字节)访问,可以随机访问的设备,属于块设备驱动。例如:硬盘、磁盘、U盘、SD卡等
网卡设备驱动:没有设备节点、操作网卡芯片实现数据收发功能的代码就是网卡设备驱动。应用程序不能直接访问网卡设备驱动程序。
3.驱动在linux中的层次
4、linux内核模块
4.1linux内核模块的三要素
三要素:入口、出口、许可证
入口:资源申请工作,在安装驱动时入口执行
static int __init demo_init(void){
return 0;
}
//static:限定作用域,这个函数只能在当前文件中使用,不能被其他传递文件调用
//__init:告诉编译器,将这个入口函数放在.init.text段中,内核执行驱动的时候就从这个段中找入口并执行
//#define __init __section(".init.text")
module __init__(demo_init);
//告诉内核驱动工程编写的驱动的入口的名字就是demo_init
出口:资源释放工作,在卸载驱动的时候执行
static void __exit demo_exit(void){
}
//static:限定作用域,这个函数只能在当前文件中使用,不能被其他传递文件调用
//__exit:告诉编译器,将这个出口函数放在.exit.text段中,内核卸载驱动的时候就从这个段中找出口并执行
//#define __exit __section(".exit.text")
module_exit(demo_exit);
//告诉内核驱动工程编写的驱动的出口的名字就是demo_exit
许可证:遵从GPL的开源协议
MODULE_LICENSE("GPL");
4.2linux内核模块的编译
驱动程序不可用gcc编译器和交叉编译器编译,需要借助Makefile进行编译。
Makefike
# KERNELDIR:= /home/linux/linux-5.10.61/ #开发板可安装的驱动
KERNELDIR:= /lib/modules/$(shell uname -r)/build/ #ubuntu可安装的驱动
#内核的路径
PWD:=$(shell pwd)
#$(shell )在执行makefile的时候起一个终端,在终端上执行pwd命令
#将结果赋值给PWD变量
all:
make -C $(KERNELDIR) M=$(PWD) modules
@#make -C $(KERNELDIR) 进入内核的路径下
@#进入到上述的路径下之后执行 make M=$(PWD) modules
@# M=$(PWD)表示只编译当前目录下的模块
clean:
make -C $(KERNELDIR) M=$(PWD) clean
@#make -C $(KERNELDIR) 进入内核的路径下
@#进入到上述的路径下之后执行 make M=$(PWD) clean
@# M=$(PWD)表示只清除当前目录下的模块
obi-m:demo.o
#告诉编译器,编译当前目录下的模块的名字叫demo,生成的驱动是demo.ko
4.3模块操作命令
安装驱动:sudo insmod xxx.ko
卸载驱动:sudo rmmod xxx
查看已安装的驱动:lsmod
5.在linux内核中使用打印语句
5.1printk打印语句的格式
printk(打印级别 +printf格式); //驱动工程师指定的消息的级别,
或
printk(和printf的控制格式是一样的); //使用的默认消息的级别
5.2内核打印级别(8种)
在linux内核中一共有八个打印级别,打印级别是用来过滤信息的。
数值越小级别越高。
KERN_EMERG "0" /* system is unusable */
KERN_ALERT "1" /* action must be taken immediately */
KERN_CRIT "2" /* critical conditions */
KERN_ERR "3" /* error conditions */
KERN_WARNING "4" /* warning conditions */
KERN_NOTICE "5" /* normal but significant condition */
KERN_INFO "6" /* informational */
KERN_DEBUG "7" /* debug-level messages */
5.3通过打印级别来过滤信息
只有当消息级别高于终端级别时,消息才会在终端上显示。
cat /proc/sys/kernel/printk
4 4 1 7
//4:终端的级别 4:默认消息级别 1:终端最高级别 7:终端最低级别
改变ubuntu默认消息的级别
su root
echo 4 3 1 7 >/proc/sys/kernel/printk
//永久改变开发板默认消息级别
/home/linux/nfs/rootfs/etc/init.d/rcS
vi rcS
//最后一行加上
echo 4 3 1 7 >/proc/sys/kernel/printk
6.4printk使用实例
#include <linux/init.h>
#include <linux/moudle.h>
static int __init demo_init(void){
printk(KERN_ERR "hello init\n");
printk("init\n");
return 0;
}
staric void __exit demo_exit(void){
printk(KERN_INFO "%s:%s:%d\n",__FILE__,__func__,__LINE__);
printk(KERN_ERR "BYE\n");
printk("exit\n");
}
module_init(demo_init);
module_exit(demo_exit);
MODILE_LICENSE("GPL");
6.5printk打印信息查看方式
1.进入虚拟终端查看
进入虚拟终端,ubuntu中:ctrl+alt+fn+[F2~F6]
退出虚拟终端的方式:ctrl+alt+fn+F1
2.通过dmesg命令查看
dmesg :能查看到从内核启动到现在这一刻起所有的打印信息
sudo dmesg -C(直接清除)/-c(先回显后清除) :清除打印信息