Linux2.6设备驱动开发

一:Linux2.6驱动设备开发的特点

1:首先是属于字符型设备注册的方法之一

这种开发接口是在Linux2.6引入的,之前的版本不支持这种开发方式,也是目前最标准的开发方式。

2:Linux2.6的设备开发

不再去限制设备号,与其对应的就是需要去申请可用的设备号。

3:Linux2.6注册完毕设备且成功之后并不会生成设备文件

对于这种情况有两种方法:

通过指令手动生成

通过内核其他接口函数生成

4:Linux2.6与杂项的区别

杂项:

优点:简单

缺点:没有分类。能注册的设备有限

Linux2.6:

有点:主设备号不限制。2^12个主设备号,设备分类;2^20个次设备号

缺点:函数流程相对于杂项复杂

总结:Linux2.6相对于杂项而言复杂,Linux2.6设备号范围比杂项大。

二:Linux2.6 驱动开发架构

1、先去申请设备号->alloc_chrdev_region();

2、初始化Linux2.6核心结构体 cdev->cdev_init();

3、添加注册设备->cdev_add

4、生成一个与之相对应的设备文件:class_create device_create

总结:在使用Linux2.6驱动时的开发步骤,需要先申请设备号,然后进行初始化,然后添加注册的设备,最后生成设备文件。

三:linux2.6驱动开发接口

现在进入到具体的开发流程

1:如何在内核中申请一个可以用的设备号

头文件:

cpp 复制代码
#include "linux/fs.h"

对应的接口函数:

cpp 复制代码
int alloc_chrdev_region(
        dev_t *dev, //uint32_t类型数字,也就是申请的设备号
        unsigned baseminor,//申请的起始次设备号
        unsigned count,//连续申请的设备数量
	    const char *name)//任意填写名字

函数功能:向内核申请目前可以用的设备号,可以申请多个设备号

函数返回值:

成功返回0,失败返回非0

释放设备号接口:

cpp 复制代码
void unregister_chrdev_region(
    dev_t from, //填写的申请的首设备号
    unsigned count//释放几个信号
)

2:linux2.6的设备注册

头文件:

cpp 复制代码
#include "linux/cdev.h"

初始化函数:

cpp 复制代码
void cdev_init(
    struct cdev *cdev, //要初始化的cdev核心结构体
    const struct file_operations *fops//与cdev做绑定,注册的设备都会用此内核接口
)

动态开辟空间的方法:kzalloc();

添加函数:

cpp 复制代码
int cdev_add(
    struct cdev *p, //cdev核心结构体
    dev_t dev, //要注册的设备的首设备号
    unsigned count//要注册的设备的数量
    )

删除函数:

cpp 复制代码
void cdev_del(
    struct cdev *p//核心结构体
)

3:设备文件的生成

手动生成:

cpp 复制代码
mknod /dev/led c 234(主设备号) 0(次设备号)

自动生成:

内核接口:

想要生成设备文件必须先创建类结构体->class

cpp 复制代码
struct class * cls = class_create(THIS_MODULE,"led_class");

销毁一个类:

cpp 复制代码
class_destroy(struct class * cls)
cpp 复制代码
有了类结构体你就可以创建设备文件了
        struct device *device_create(
        struct class *class,
        struct device *parent,
        dev_t devt,
        void *drvdata,
        const char *fmt, ...
) *
class:
    刚才得到的类结构体
*parent:
    设备的父设备->没有父设备->NULL
*devt
    设备的设备号
*drvdata
    创建设备附带的私有数据->NULL
*fmt,...:
    跟 printf 一样的
直接当作字符串传递也是一样的
他就是你创建设备文件的名字!

如何销毁一个设备文件:

cpp 复制代码
void device_destroy(struct class *class, dev_t devt)
class:
    类结构体
devt:
    设备号

4:事例:linux2.6下的LED驱动

cpp 复制代码
#include"linux/fs.h"
#include"linux/module.h"
#include"linux/kernel.h"
#include"linux/cdev.h"
#include"linux/gpio.h"
#include"device.h"

dev_t  mydevnum;//设备号
struct cdev mycdev;//Cdev核心结构体
struct file_operations ops;//内核层的文件操集合结构体
struct class * cls;//类设备文件结构体
//开灯回调函数

int led_on (struct inode *i, struct file *f)
{
	gpio_set_value(21,1);
	gpio_set_value(22,0);
	return 0;
}
//关灯回调函数
int led_off (struct inode *i, struct file *f)
{
	gpio_set_value(21,0);
	gpio_set_value(22,1);
	return 0;
}
//入口函数
static int __init myled_init(void)
{
	//申请设备号
	int ret = alloc_chrdev_region(&mydevnum,0,1,"myled");
	if(ret < 0)
	{
		return -EINVAL;//加载失败
	}
	printk("主设备:%d\t\t次设备:%d\r\n",mydevnum>>20,mydevnum&0xFFFFF);
	//初始化Linux2.6 cdev结构体
	
	ops.owner = THIS_MODULE;
	ops.open = led_on;
	ops.release =led_off;
	cdev_init(&mycdev,&ops);
	//添加cdev设备
	cdev_add(&mycdev,mydevnum,1);
	//生成一个类设备文件
	cls=class_create(THIS_MODULE, "led_class");
	//创建设备文件
	device_create(cls,NULL,mydevnum,NULL,"led");
	//初始化硬件
	gpio_request(21,"led1");
	gpio_request(22,"led2");
	gpio_direction_output(21,0);
	gpio_direction_output(22,0);
	
	return 0;
}
//出口函数
static void __exit myled_exit(void)
{
	//卸载程序只有一个原则 ->倒序
	gpio_free(21);
	gpio_free(22);
	device_destroy(cls,mydevnum);
	class_destroy(cls);
	cdev_del(&mycdev);
	unregister_chrdev_region(mydevnum,1);
}
module_init(myled_init);
module_exit(myled_exit);
MODULE_LICENSE("GPL");
相关推荐
cxr8281 天前
SPARC方法论在Claude Code基于规则驱动开发中的应用
人工智能·驱动开发·claude·智能体
sukalot1 天前
window显示驱动开发—显示适配器的子设备
驱动开发
Evan_ZGYF丶2 天前
【RK3576】【Android14】如何在Android14下单独编译kernel-6.1?
linux·驱动开发·android14·rk3576
sukalot3 天前
window显示驱动开发—视频呈现网络简介
驱动开发
sukalot3 天前
window显示驱动开发—为头装载和专用监视器生成自定义合成器应用(二)
驱动开发
zwhSunday3 天前
Linux驱动开发(1)概念、环境与代码框架
linux·运维·驱动开发
sukalot4 天前
window显示驱动开发—为头装载和专用监视器生成自定义合成器应用(三)
驱动开发
sukalot4 天前
window显示驱动开发—为头装载和专用监视器生成自定义合成器应用(一)
驱动开发
cxr8285 天前
基于Claude Code的 规范驱动开发(SDD)指南
人工智能·hive·驱动开发·敏捷流程·智能体
zwhSunday5 天前
Linux驱动开发(2)进一步理解驱动
linux·驱动开发