一个最基本的Linux驱动开发框架和编译驱动方式

本文介绍了Linux驱动开发的基础框架,包括驱动文件的编写,如头文件的包含、驱动入口和出口的定义,以及申明。详细阐述了编译驱动的两种方式:与内核一起编译和编译成模块。并提供了每种方式的具体步骤,包括修改Makefile、配置内核、编译和加载驱动模块。通过本文,读者可以了解驱动开发的基本流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

这里给大家介绍最基本的驱动开发框架


一、编写驱动文件

主要有下面几个部分组成:

1.相关头文件

这两个头文件黑丝驱动开发必须包含的头文件

#include<linux/init.h>
#include<linux/module.h>

2.驱动入口 &出口

static int hello_init(void)
{
    printk("hello world\n");
    return 0;

}

static void hello_exit(void)
{
    printk("by-by\n");
    
}


module_init(hello_init);//入口
module_exit(hello_exit);//出口

入口函数一般是主要完成平台总线的注册等操作,出口函数就是对资源的回收

3.申明

由于Linux是开源的所以需要声明凭证GPL,同时内核也提供了很多相关的宏,给写着描述

MODULE_LICENSE("GPL");//这个是必须要写的,不然编译会有问题
MODULE_AUTHOR("ljm");//作者
MODULE_DESCRIPTION("这是一个基本的驱动框架");

完整代码

#include<linux/init.h>
#include<linux/module.h>



static int hello_init(void)
{
    printk("hello world\n");
    return 0;

}

static void hello_exit(void)
{
    printk("by-by\n");
    
}

module_init(hello_init);
module_exit(hello_exit);


MODULE_LICENSE("GPL");
MODULE_AUTHOR("ljm");


二、编译驱动的方式

我们编译驱动有两种方式,一种是和内核一起编译,另一种是编译成内核模块,这两种有什么区别:
和内核一起编译:
对于和内核一起编译来说,是直接把驱动文件添加到内核源码的driver目录下的某一目录下,之后和内核一起编译,这中方式适合我们完成驱动调试好之后

编译成内核模块:
对于编译成内核模块来说,是没有这种要求,我们可以把驱动放在任何地方,可以单独编译成模块即带有.ko的文件,之后我们再使用命令insmod xxx.ko来加载驱动即可,优点就是我们不需要的话可以直接使用命令rmmod xxx.ko卸载掉,而不需要再去修改编译内核,可以看出这种方式适合我们在驱动开发时使用,适合我们调试,节省时间。


三、编译驱动

下面使用上面介绍的两种方式来演示一下如何编译驱动:

1. 和内核一起编译:

进入到内核源码目录下的如下目录:

drivers/misc

1)添加驱动文件,这个文件就是我们前面写好的文件
在这里插入图片描述

2)修改Makefile文件(也是在该目录下)
这个配置就是告诉makefile文件要把hellmodule.c编译
在这里插入图片描述

补充:这里除了这种配置外还可以按照下面做法配置:
细心的朋友可能注意到自己添加的哪部分为什么是obj-y而别人是obj-$(变量),如下:
在这里插入图片描述
这里解释一下,-y表示默认编译到内核中,而 obj-¥(变量)表示要不要编译,编译成什么状态由这个变量决定,那么问题来了,这个变量又是哪来的,在哪里设置?这个问题也就是要说的第二种配置:

还是和前面一样,把hellomodule.c拷贝到drivers/misc目录下
(也可以在misc下新建一个目录给自己的驱动,不过需要在自己驱动文件同级目录下写Kconfig,Makefile,还有修改misc的Kconfig文件添加自己Kconfig的路径 下面不介绍这种)

在这里插入图片描述
修改Makefile文件
表示告诉makefil文件hellomodule.c要不要编译,编译成什么状态(模块或者和内核一起编译)由变量CONFIG_HELLOMODULE决定
在这里插入图片描述
变量CONFIG_HELLOMODULE要依据下面决定
修改Kconfig文件:
在这里插入图片描述具体意思如下:


config HELLOMODULE  //变量,如果我们选择编译到内核相当于*,模块相当于m,不编译就空  ,图形配置决定,后面会说
        tristate "HELLOMODULE"  //表示该驱动有三态,* M 空
        default n  默认不编译
        help
          this is my first driver. //帮助信息

图形配置该驱动
输入以下命令:

 export ARCH=arm64 //导出环境变量为arm64
 make rockchip_linux_defconfig //配置默认的内核配置文件,会产生.config文件,即最终的配置文件
 

在这里插入图片描述
输入以下命令进入图形配置:

 make menuconfig

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这里我选择编译到内核
在这里插入图片描述
然后保存配置
在这里插入图片描述
在这里插入图片描述
之后退出即可
保存退出之后,输入以下命令保存配置内核文件。

make savedefconfig

输入以下命令保存到默认的配置文件中:

cp defconfig arch/arm64/configs/rockchip_linux_defconfig

之所以进行这两步,是因为我们后面使用的是瑞芯微的脚本编译内核,而脚本里面默认编译的配置文件就是rockchip_linux_defconfig,所以我们得更新一下,不然看不到,因为我们的配置文件.config,并没有被这个脚本使用,当然你也可以使用直接使用make命令,但是使用这种方法编译出来的貌似还不能用

在这里插入图片描述

接下来后面的步骤是一样

3)重新编译内核
回到SDK的目录下输入以下命令编译
在这里插入图片描述

4)编译完成:
在这里插入图片描述

5)烧录新编译的镜像:
在这里插入图片描述
前面章节已经介绍了如何烧录传送门

6)烧录完成后在串口打印中可以看到如下所示的打印:
在这里插入图片描述
这个打印消息就是我们驱动加载的时候打印的消息
在这里插入图片描述

可以看出这里打印消息一模一样,表示已经加载驱动成功

2. 编译成驱动模块:

前面的方法中我们是将驱动和内核一起编译,但是我们每次修改驱动就要从新编译一次内核,特别费时间,所以我们经常把驱动编译成模块

1)编写Makefile文件

KERNEL_DIR=/home/topeet/Linux/linux_sdk/kernel  #内核源码路径

ARCH=arm64  #芯片架构
CROSS_COMPILE=/usr/local/arm64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-  #编译器
export  ARCH  CROSS_COMPILE

obj-m := hellomodule.o #编译成内核模块
all:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean   #伪命令

clean:
	$(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean	

读者要依据自己的内核源码路径和编译器的路径设置

其中对于编译器,瑞芯微提供的SDK里面就有编译器,我们只需要使用这个即可
在这里插入图片描述
如下编写Makefile设置:

KERNEL_DIR=/home/topeet/Linux/linux_sdk/kernel

ARCH=arm64
CROSS_COMPILE=/home/topeet/Linux/linux_sdk/prebuilts/gcc/linux-x86/aarch64/gcc-linaro-6.3.1-2017.05-x86_64_aarch64-linux-gnu/bin/aarch64-linux-gnu-
export  ARCH  CROSS_COMPILE

obj-m := hellomodule.o
all:
        $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) modules

.PHONE:clean copy

clean:
        $(MAKE) -C $(KERNEL_DIR) M=$(CURDIR) clean      

copy:
        sudo  cp  *.ko  /home/embedfire/workdir

如果你出现如下错误,那么就说明你还没有设置好编译器的环境:
在这里插入图片描述
为了方便我们以后编写应用层的代码,我们最好把这个编译器环境导出来感兴趣的读者可以看这篇文章传送门

2).编译
把Makefile文件和驱动文件放在一起,如下:
在这里插入图片描述
执行以下命令:

make //编译

在这里插入图片描述

make clean //清除编译

其中hellomodule.ko就是我们的驱动模块在这里插入图片描述


3.开发板加载驱动模块

通过网络Nfs或者其他方式把hellomodule.ko文件发给开发板,在开发板中执行以下操作:

insmod hellomodule.ko  //表示加载驱动模块

在这里插入图片描述

rmmod hellomodule.ko //卸载模块

在这里插入图片描述

总结

本文从零开始搭建了驱动的编写,编译,加载到实现,相信对于没有基础的读者会有一定的帮助,如果有帮助到你的地方清点击收藏+关注哦

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不知道起个啥名“”

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值