字符设备驱动程序自动创建设备节点详解

字符设备驱动程序自动创建设备节点详解,第1张

1、设备节点介绍

(1)在linux中一切皆是文件,对上层程序来说设备驱动程序不过就是设备文件,在我们向内核注册好驱动程序后,需要创建对应的设备节点,然后上层应用程序通过读写设备节点的方式去 *** 作硬件;
(2)设备节点本质上就是文件,不是普通类型的文件,是字符设备文件、块设备文件、网络设备文件等特殊文件,但是都是用统一的open、read等函数去 *** 作;
(3)设备节点在"/dev/"目录下;

2、手动创建设备节点

(1)在驱动程序注册成功后,可以用mknod命令可以手动创建设备节点;
(2)比如:mknod /dev/com1 c 237 1,创建主设备号是237次设备号是1的设备节点/dev/com1;
补充:必须想办法知道驱动程序注册时候的主次设备号;

3、用udev自动创建设备节点 3.1、udev介绍

(1)udev 是一个工作在用户空间的工具, 它能根据系统中硬件设备的状态动态的更新设备文件, 包括设备文件的创建, 删除, 权限等;
(2)udev 运行在用户模式, 而非内核中;
(3) 创建的文件通常都定义在/dev 目录下,但也可以在配置文件中指定。

自动创建设备节点的步骤

(1)在/sys/class/目录下创建一个类;
(2)在对应的类下面创建设备;

3.2、创建类和注销类
//创建类
#define class_create(owner, name)		\
({						\
	static struct lock_class_key __key;	\
	__class_create(owner, name, &__key);	\
})

//注销类:传入创建类时返回的struct class结构体指针
void class_destroy(struct class *cls)
{
	if ((cls == NULL) || (IS_ERR(cls)))
		return;

	class_unregister(cls);
}

创建类:

(1)返回值:返回一个struct class结构体指针;
(2)owner:模块所有者,一般填THIS_MODULE;
(3)name:类名字;
(4)函数功能:返回一个struct class结构体指针,在/sys/class/目录下新建名字为name的类;

3.3、创建设备和注销设备
//创建类下面的设备
struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, void *drvdata, const char *fmt, ...);

//注销创建的设备:传入struct class结构体指针和主次设备号
void device_destroy(struct class *class, dev_t devt);

创建设备:
(1)返回值:struct device结构体指针,用来表示新创建的设备;
(2)class:创建的类,就是这个设备属于哪个类;
(3)parent:设备的父节点,没有就填NULL;
(4)devt:驱动程序的主次设备号;
(5)drvdata:添加到设备的数据,调用的时候会用到,没有就填NULL;
(6)fmt:这是个可变参数,传入的是设备的名字;fmt可以和sprintf()函数做类比,可以用%d、%s等来构造设备的名字;
(7)函数功能:在指定类创建名字是fmt的设备,并在创建**/dev/fmt**设备节点;

3.4、自动创建设备节点的代码实例
static int major = 237;
static int minor = 0;
static dev_t devno;
struct device *class_dev = NULL;
struct class *cls;

static struct file_operations hello_ops = 
{
	.open = hello_open,
	.release = hello_release,
};

static int hello_init(void)
{
	int result;
	int error;
	
	//注册字符驱动程序
	result = register_chrdev(major, "hello", &hello_ops);

	//创建类
	cls = class_create(THIS_MODULE, "hellocls");

	//生成设备号
	devno = MKDEV(major, minor);
	
	//创建设备
	class_dev = device_create(cls, NULL, devno, NULL, "hellodev");
	return 0;

out_err_2:
	class_destroy(cls);
out_err_1:
	unregister_chrdev(major,"hello");
	return 	result;
}
3.5、代码实现效果

(1)在/sys/class/目录下多了hellocls类;
(2)hellocls类下面有hellodev设备;
(3)hellodev设备下面有文件,里面记录了主次设备号,设备名等信息;
(4)会在/dev/目录下创建hellodev设备的设备节点:/dev/hellodev;

4、两种创建方式对比

(1)手动创建设备节点:必须在设备驱动注册成功之后拿到主次设备号,用mknod命令去创建设备节点,虽然可以用脚本来实现,但是还是比较笨拙;
(2)自动创建设备节点:直接在设备驱动代码中添加自动创建设备节点的代码,驱动程序注册成功后便创建好了设备节点,明显比较方便;
总结:尽量使用自动创建设备节点,少使用手动创建设备节点;

参考内容:博主“一口linux”的驱动讲解部分;

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/878117.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-13
下一篇 2022-05-13

发表评论

登录后才能评论

评论列表(0条)

保存