编译Linux驱动程序
Linux是宏内核(把资源全部放在一个容器内,整体编译,有两种编译方式:静态编译,模块编译),windows是微内核(分容器,部分编译)
模块编译:将驱动编译成内核模块,独立于Linux内核以外
静态编译:将驱动放在Linux内核里,编译Linux内核,将驱动编译到Linux内核里面
(Linux内核模块:Linux系统中一个特殊的机制,将使用频率低或者暂时不用的功能编译成内核模块,在需要的时候在动态加载到内核里面。使用内核模块可以减小内核的体积,加快启动速度。并且可以在系统运行的时候、加载或卸载、驱动,无需重启系统。内核模块的后缀是 .ko)
模块编译
- 在驱动源码同级路径下创建Makefile文件(shell格式严格缩进,vim打开检查格式错误)
- 编写Makefile文件内容,KERNELDIR是内核源码的实际路径
- 执行make生成.ko文件
# ARCH是架构
ARCH?=arm
# KERNELDIR是内核源码路径
ifeq ($(ARCH),arm)
KERNELDIR:= /home/student/linux-5.4.31
else
KERNELDIR:= /lib/modules/$(shell uname -r)/build
endif
# PWD 当前模块路径
PWD:=$(shell pwd)
all:
make -C $(KERNELDIR) M=$(PWD) modules
#@ make -C $(KERNELDIR) 进入内核目录下读取内核目录下的Makefile文件
#@ 然后执行 make M=$(PWD) modules
#@ make modules 进行模块化编译
#@ M= 编译模块的路径,默认是内核顶层目录
clean:
make -C $(KERNELDIR) M=$(PWD) clean
# 要编译的模块
obj-m:= hello_world.o
#详解,例如:我们的源文件是 hello_world.c 则-c编译后就是 hello_world.o
cp:
cp hello_world.ko /source/rootfs/root/
内核模块相关命令(加sudo)
ubantu:modinfo hello_world.ko//打印驱动设备信息
加载模块:
- insmod xxx.ko加载Linux内核模块
- modprobe [options] xxx.ko同时依赖模块也加载
卸载模块:
- rmmod xxx.ko移除载入的Linux内核
查看模块打印载入信息:
- lsmod 列出载入linux的内核模块,cat/proc/module查看模块加载是否成功
- modinfo xxx.ko打印模块信息
- dmesg 打印加载的内核模块记录信息
- dmesg -c回显并清除打印信息
- dmesg -C 清空载入的内核模块的记录信息
printk函数
内核打印函数printk,应用层函数printf
printk(打印级别“打印信息”)或printk(”打印信息”)
8种打印等级:数值越小级别越高
#define KERN_EMERG "0" /* 系统无法使用 */
#define KERN_ALERT "1" /* 必须立即采取行动 */
#define KERN_CRIT "2" /* 危笃状态 */
#define KERN_ERR "3" /* 出错状态 */
#define KERN_WARNING "4" /* 警报条件 */
#define KERN_NOTICE "5" /* 正常但重要的状况 */
#define KERN_INFO "6" /* 信息性 */
#define KERN_DEBUG "7" /* 调试信息 */