让你的linux驱动可以自己创建设备节点

什么是设备节点

前面我们讲过,在驱动中实现file_operations结构体并注册进内核时,我们使用该驱动的时候自己手动用mknod手动创建的设备节点,这个设备节点是用来被应用程序打开和操作的,是应用和驱动交互不可缺少的。

怎么让驱动自动创建节点

需要使用到两个函数,一是class_create()函数,还有一个是device_create()函数。那么他们有什么作用呢?请看:
1、class_create(),可以理解为该函数会在/dev/下创建一个目录,如:input目录、bus目录等。
2、device_create(),可以理解为在class_create()创建的目录下创建一个设备节点。所以在device_create()就可以传入class_create()创建的类。
贴出函数原型供大家参考:

struct class *class_create (struct module *owner, const char *name);
struct device *device_create(struct class *class, struct device *parent, dev_t devt, void *drvdata, const char *fmt, ...)

顺便贴出销毁设备和类的函数原型:

void device_destroy(struct class *class, dev_t devt);
void class_destroy(struct class *cls);

具体代码

该代码在上节linux应用与驱动的交互方式之file_operations结构体代码的基础上增加了自动创建设备节点的方法,需要注意的是,该代码并未控制实际的硬件,只是一个框架,可以加上自己的代码实现自己的功能:


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

#define XXX_MAJOR 	200 		/* 主设备号 */
#define XXX_NAME 	"xxx_test" 	/* 设备名 */

struct class * xxx_class; /* 类 */
struct device * xxx_device; /* 设备 */


static int xxx_open(struct inode *inode, struct file *filp)
{
	//通常返回:0 成功;其他 失败
	return 0;
}

static ssize_t xxx_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt)
{
	//通常返回:读取的字节数;小于0,表示读取失败
	return 0;
}

static ssize_t xxx_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt)
{
	//通常返回:写入的字节数;小于0,表示写入失败
	return 0;
}

static int xxx_release(struct inode *inode, struct file *filp)
{
	//通常返回:0 成功;其他 失败
	return 0;
}

//本xxx_fops只列出了部分常用的操作
static const struct file_operations xxx_fops = {
	//owner 拥有该结构体的模块的指针,一般设置为 THIS_MODULE
	.owner 		= THIS_MODULE,
	//open 函数用于打开设备文件,用户程序打开设备文件会得到一个设备描述符,并执行驱动指定的open函数(不管驱动有无open函数,用户使用都需要打开)
	.open 		= xxx_open,	
	//read 函数用于读取设备文件,应用执行read时会调用该函数
	.read 		= xxx_read,
	//write 函数用于向设备文件写入(发送)数据,应用执行write时会调用该函数
	.write 		= xxx_write,
	//release 函数用于释放(关闭)设备文件,与应用程序中的 close 函数对应
	.release 	= xxx_release,
};

//模块初始化函数,在模块装载的时候调用
static int __init xxx_init(void)
{
	int ret = 0;
	
	//主设备号为0,自动分配设备号,返回值是分配的设备号
	ret = register_chrdev(XXX_MAJOR, XXX_NAME, &xxx_fops);
	//返回值为负数,注册失败
	if(ret < 0)
	{
		return -1;
	}
	
	//创建类,在/dev目录下生产xxx目录
	xxx_class = class_create(THIS_MODULE, "xxx");
	//创建设备节点,在/dev/xxx/目录下生成xxx_driver设备文件
	xxx_device = device_create(xxx_class, NULL, XXX_MAJOR, NULL, "xxx_driver");

	return 0;
}

//模块退出函数,在模块卸载的时候调用
static void __exit xxx_exit(void)
{
	//注销字符设备驱动
	unregister_chrdev(XXX_MAJOR, XXX_NAME);
	
	//销毁设备节点,会删除/dev/xxx/目录下的xxx_driver设备文件
	device_destroy(xxx_class, XXX_MAJOR);
	//销毁类,会删除/dev目录下的xxx目录
	class_destroy(xxx_class);
}

//向内核表明初始化函数,在模块装载的时候调用
module_init(xxx_init);
//向内核表明退出函数,在模块卸载的时候调用
module_exit(xxx_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("xiaoShuATao");

注:作者水平有限,如有错误,请大家及时指出,我会第一时间修改,谢谢大家了。
版权说明:可自由转载使用,转载请注明出处。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值