Linux驱动开发——新字符设备驱动开发


系列文章:
Linux驱动开发——字符设备驱动开发
Linux驱动开发——LED驱动开发

1 概述

之前的字符设备驱动,使用register_chrdev函数注册设备,使用的时候需要mknod命令创建设备节点。register_chrdev和unregister_chrdev是老版本的驱动使用的函数,新的字符设备驱动已经不再使用,而是使用Linux内核推荐的新字符设备驱动API函数。

2 新字符设备驱动原理

2.1 分配和释放设备号

使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可,但是这样会
带来两个问题:

  • 1、需要我们事先确定好哪些主设备号没有使用。
  • 2、会将一个主设备号下的所有次设备号都使用掉,比如现在设置 LED 这个主设备号为
    200,那么 0~1048575(2^20-1)这个区间的次设备号就全部都被 LED 一个设备分走了。这样太浪
    费次设备号了!一个 LED 设备肯定只能有一个主设备号,一个次设备号。

解决这两个问题最好的方式是向Linux内核申请,需要几个就申请几个,由Linux内核分配可以使用的设备号。
如果没有指定设备号的话就使用:

int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)

如果给定了设备的主设备号和次设备号就使用:

int register_chrdev_region(dev_t from, unsigned count, const char *name)

from表示要申请的设备号,也就是给定的设备号,count表示要申请的数量,name是设备的名字。
释放设备号的时候,使用以下函数:

void unregister_chrdev_region(dev_t from, unsigned count)

2.2 新字符设备注册方法

  1. 字符设备结构
    Linux中使用cdev结构体表示一个字符设备,cdev结构体在 include/linux/cdev.h文件中,定义如下:
struct cdev {
   
	struct kobject kobj;
	struct module *owner;
	const struct file_operations *ops;
	struct list_head list;
	dev_t dev;
	unsigned int count;
} __randomize_layout;

这里面有两个重要的变量:ops和dev,ops是字符设备文件操作函数集合file_operations这个结构体变量,dev则是dev_t类型的设备号。在编写设备驱动之前,需要定义一个cdev类型的变量,表示一个字符设备。
2. cdev_init函数
定义好cdev变量之后,需要通过cdev_init函数对其进行初始化,其声明如下:

void cdev_init(struct cdev *, const struct file_operations *);
  1. cdev_add函数
    cdev_add函数用于向Linux内核中添加字符设备,声明如下:
int cdev_add(struct cdev *, dev_t, unsigned);
  1. cdev_del函数
    cdev_del函数从Linux内核中删除相应的字符设备,其声明如下:
void cdev_del(struct cdev *);

3 自动创建设备节点

之前的驱动开发方式,不会自动创建设备节点,module被加载完成之后,需要手动通过mknod命令创建设备节点,这里配置好之后,加载驱动的时候就会自动创建对应的设备节点

3.1 mdev机制

mdev是busybox自带的一个简化版的udev,mdev和udev都是用于管理虚拟设备的机制,它允许动态地创建、配置、启动和销毁设备文件。可以检测系统中硬件的设备状态,可以根据系统中硬件设备来创建或者删除设备文件。
开发版启动的时候会启动udev
在这里插入图片描述

3.2 创建和删除类

自动创建设备节点的工作是在驱动程序入口函数中完成的,一般在cdev_add函数后面添加自动创建设备节点相关代码。首先要创建一个 class 类,class 是个结构体,定义在文件include/linux/device.h 里面。class_create 是类创建函数,class_create 是个宏定义,内容如下:

extern struct class * __must_check __class_create(struct module *owner,
						  const char *name,
						  struct lock_class_key *key);
extern void class_destroy(struct class *cls);

/* This is a #define to keep the compiler from merging different
 * instances of the __key variable */
#define class_create(owner, name)		\
({
     						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})

将宏定义展开之后,内容如下:

struct class *class_create (struct module *owner, const char *name)

一共有两个参数,owner一般为THIS_MODULE,参数name是类的名字,返回值是一个指向结构体class的指针,也就是创建的类。
卸载驱动的使用通过class_destroy函数进行卸载

3.3 创建设备

上面创建好类之后还不能自动创建设备节点,还需要在类下创建一个设备,使用device_create函数进行创建

struct device *device_create(struct class *cls, struct device *parent,
			     dev_t devt, void *drvdata<
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值