> 文章列表 > linux驱动学习1

linux驱动学习1

linux驱动学习1

内核模块加载/卸载

  • 使用insmod命令加载
  • 使用rmmod命令卸载

内核模块入口/出口

  • module_init():加载模块式该函数自动执行,进行初始化操作
  • module_exit():卸载模块时函数自动执行,进行清理操作

内核模块信息声明

  • MODULE_LICENSE():表示模块代码接受的软件许可协议,Linux内核遵循GPL V2开源协议,内核模块与linux内核保持一致即可。
  • MODULE_AUTHOR():描述模块的作者信息
  • MODULE_DESCRIPTION():对模块的简单介绍
  • MODULE_ALIAS():给模块设置一个别名

内核模块实验1

编译4.19.71版本内核

内核模块的功能需要依赖内核提供的各种底层接口

1.下载linux内核源码

github:git clone https://github.com/Embedfire/ebf-buster-linux.gitgitee:git clone https://gitee.com/Embedfire/ebf-buster-linux.git

2.安装必要环境工具库

sudo apt install make gcc-arm-linux-gnueabihf gcc bison flex libssl-dev dpkg-dev lzop

3.一键编译内核

sudo ./make_deb.sh

4.获取编译出来的内核相关文件

/home/pi/build

内核模块头文件

  • include <linux/module.h>:包含内核模块信息声明的相关函数
  • include <linux/init.h>:包含了 module_init()和 module_exit()函数的声明
  • include <linux/kernel.h>:包含内核提供的各种函数,如printk

内核模块打印函数

  • printf:glibc实现的打印函数,工作于用户空间
  • printk:内核模块无法使用glibc库函数,内核自身实现的一个类printf函数,但是需要指定打印等级。
    • #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>” 调试信息

查看当前系统printk打印等级:cat /proc/sys/kernel/printk

  • 当前控制台日志级别
  • 默认消息日志级别
  • 最小的控制台级别
  • 默认控制台日志级别

打印内核所有打印信息:dmesg

  • 内核log缓冲区大小有限制,缓冲区数据可能被冲掉

Makefile分析

  • KERNEL_DIR:指向linux内核具体路径
  • export:导出变量给子Makefile使用
  • obj-m := <模块名>.o:定义要生成的模块
  • $(MAKE):Makefile的默认变量,值为make
  • 选项”-C”:让make工具跳转到linux内核目录下读取顶层Makefile
  • M=:表示内核模块源码目录
  • $(CURDIR):Makefile默认变量,值为当前目录所在路径
  • make modules:执行Linux顶层Makefile的伪目标,它实现内核模块的源码读取并编译为.ko文件

编译内核模块

make

把生成的内核模块拷贝到nfs共享目录

make copy

开发板加载内核模块

insmod xxx.ko

Makefile 文件,注意M需要大写

KERNEL_DIR=/home/shanghai/ebf-linux/ebf-buster-linux/build_image/buildARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
export  ARCH  CROSS_COMPILE
#注意hello.o需要与原文件名一致
obj-m := hello.o
all:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules
.PHONY:clean copy
clean:$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) cleancopy:sudo cp *.ko /home/shangahi/workdir

hello.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>static int __init hello_init(void)
{printk(KERN_EMERG "[KERN_EMERG] hello world module init\\n");printk("[default] hello world module init\\n");
}static void __exit hello_exit(void)
{printk("[default] hello world module exit\\n");
}module_init(hello_init);
module_exit(hello_exit);MODULE_LICENSE("GPL2");
MODULE_AUTHOR("cwd");
MODULE_DESCRIPTION("hello world module");
MODULE_ALIAS("test_module");