【Kernel】驱动编译的两种方式:编译成模块、编译进内核(使用杂项设备驱动模板)

【Kernel】驱动编译的两种方式:编译成模块、编译进内核(使用杂项设备驱动模板)

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

杂项设备驱动代码模板

/*********这几个是必备的头文件**********/

#include

#include

#include

#include

#include

#include

int misc_open(struct inode* inode, struct file *file)

{

printk("[misc]open misc\n"); // 打开设备信号

return 0;

}

int misc_release(struct inode *inode, struct file *file)

{

printk("[misc]release misc\n"); // 释放设备

return 0;

}

// 应用层读取驱动层信号

ssize_t misc_read(struct inode *inode, char __user *ubuf, size_t size, loff_t *loff_t)

{

char kbuf[128] = "kernel to user str";

if(copy_to_user(ubuf, kbuf, sizeof(kbuf)) == 0)

{

printk("return data error");

}

return 0;

}

// 应用成写入驱动层信号

ssize_t misc_write(struct inode *inode, char __user *ubuf, size_t size, loff_t *loff_t)

{

char kbuf[128];

if(copy_from_user(kbuf,ubuf,size) == 0)

{

printk("[user to kernel]%s\r\n",kbuf);

}

return 0;

}

// 文件操作结构体

struct file_operations misc_fops = {

.owner = THIS_MODULE,

.open = misc_open,

.release = misc_release,

.read = misc_read,

.write = misc_write,

};

struct miscdevice misc_dev = {

.minor = MISC_DYNAMIC_MINOR,// 次设备号为杂项设备

.name = "misc_mod", // 设备节点名字

.fops = &misc_fops // 绑定文件操作结构体指针

};

static int __init misc_init(void)

{

int ret;

ret = misc_register(&misc_dev);

if(ret < 0)

{

printk("misc_dev register error\r\n");

return -1;

}

return 0;

}

static void __exit misc_exit(void)

{

misc_deregister(&misc_dev);

}

module_init(misc_init); // 加载初始化信号绑定

module_exit(misc_exit); // 卸载信号绑定

MODULE_AUTHOR("stylle"); // 作者

MODULE_DESCRIPTION("misc driver"); // 驱动介绍可以不写

MODULE_LICENSE("GPL");// 开源协议

杂项设备的驱动是驱动开发中最简单最方便的,核心就是处理write信号和read信号做出对应的反应。

驱动编译成模块

如果需要将驱动编译成模块前提是有编译好的kernel,并且开发板是烧录的该版本的kernel,编译成模块我们只需要新建一个Makefile文件:

ARCH = arm # 32位:arm 64位:arm64

# 交叉编译器前缀 例如我这里交叉编译gcc就是arm-linux-gcc这里就填写 arm-linux-

CROSS_COMPILE = aarch64-linux-gnu-

KDIR := /home/qlqcetc/nuc977bsp/02.linux_kernel # 编译完成的内核路径

TARGET = misc # 目标文件名:misc.ko

EXEC = $(TARGET)

obj-m :=$(TARGET).o

PWD :=$(shell pwd)

all:

$(MAKE) -C $(KDIR) M=$(PWD) modules

clean:

rm -rf *.o *~core.depend.*.cmd *.ko *.mod.c .tmp_versions $(TARGET)

然后我们只需要make就会生成.ko文件,然后将ko文件拷贝到开发板中,加载驱动使用insmod、卸载内核使用rmmod。

insmod misc.ko

ls /dev # 打印驱动列表查看我们的misc_mod是否加载进去

rmmod misc

ls /dev # 卸载成功后应该会消失

驱动编译进内核

如果要将驱动编译到内核中去则需要新建两个文件一个Makefile一个Kconfig

Makefile

obj-$(CONFIG_MISC) += misc.o #这里的misc.o文件名是需要对应自己的.c文件生成的.o文件名

Kconfig

config MISC

tristate "auto reg" # 显示在图形化配置菜单中的名字

depends on HELLO # 依赖HELLO 模块才能选择

help

auto reg help # 图形化配置的help提示信息

相关的Kconfig配置还有以下几条:

config MISC配置选项的名称

tristate 表示的驱动的状态,三种状态是把驱动编译成模块,把驱动编译到内核,不编译。与之对应的还 有 bool 分别是编译到内核,不编译

A depends on B 表示只有在选择 B 的时候才可以选择 A 比如我想直接去掉 LED 相关的驱动,我们直接改.config 文件可以吗?可以,但是不推荐。如果有依赖的话, 直接修改.config 是不成功的。

select 反向依赖,该选项被选中时,后面的定义也会被选中。

然后我们还需要修改上一层目录的Makefile和上一层的Kconfig也就是Kernel下的driver目录下的Makefile和Kconfig文件

Makefile的更改就是加上驱动所在的路径

obj-y表示编译到内核中

obj-m表示编译成模块

obj-$表示可以在图形化配置中进行选择

Kconfig的更改就是加上驱动所在的路径下的Kconfig文件

然后进入kernel根目录下使用make menuconfig命令就可以进入设备驱动配置,这里还需要有一个点需要主义就是这个menu这里menu对应的参数就是我们驱动列表的参数

因为我们这里的Kconfig中source填写在最后所以这里的选项也应该是在最后,然后我们使用空格就可以选择驱动编译的情况:

*表示编译进内核

M表示编译成模块

🌟 相关推荐

育碧公布《舞力全开2024》完整歌曲列表
附近的36524超市

育碧公布《舞力全开2024》完整歌曲列表

📅 01-23 👀 3901
如何合理分配部门奖金包?
附近的36524超市

如何合理分配部门奖金包?

📅 09-17 👀 2454
DOTA2小黑
附近的36524超市

DOTA2小黑

📅 08-08 👀 1923