linux驱动学习——自动创建设备节点

文章目录

    • 7.1、udev
    • 7.2、函数说明
    • 7.3、示例代码

7.1、udev

linux传统上使用静态设备创建方法,因此大量设备节点在/dev下创建(有时上千个),而不管相应的硬件设备是否真正存在。

采用udev的方法,只有被内核监测到的设备,才会去为它们创建设备节点。

当插入新设备——加入驱动模块——在sysfs上注册新的数据后,udev会创建新的设备节点。


linux系统中/sys/devices/virtual/input/xxx路径下,dev文件和uevent文件会存储驱动的设备号以及设备的名称。

7.2、函数说明

  • class_create 创建一个类
/* 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);	\
})

参数:

  • @owner:THIS_MOUDLE
  • @name:类名字

返回值

定义一个struct class的指针变量cls接受返回值,然后通过IS_ERR(cls)判断是否失败;

如果成功这个宏返回0,失败返回非0值;可以通过PTR_ERR(cls)来获得失败返回的错误码。

  • class_destroy 注销类
/**
 * class_destroy - destroys a struct class structure
 * @cls: pointer to the struct class that is to be destroyed
 *
 * Note, the pointer to be destroyed must have been created with a call
 * to class_create().
 */
void class_destroy(struct class *cls)
{
	if ((cls == NULL) || (IS_ERR(cls)))
		return;

	class_unregister(cls);
}
  • device_create 导出设备信息到用户空间
struct device *device_create(struct class *class, struct device *parent,
			     dev_t devt, void *drvdata, const char *fmt, ...)
{
	va_list vargs;
	struct device *dev;

	va_start(vargs, fmt);
	dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
	va_end(vargs);
	return dev;
}
  • 参数:
    • @class:class_create创建的类;
    • @parent:父节点,可以为NULL
    • @devt:设备号
    • @drvdata:参数,可以为NULL
    • @fmt:可变参数

  • device_destroy 注销设备信息
void device_destroy(struct class *class, dev_t devt)
{
	struct device *dev;

	dev = class_find_device(class, NULL, &devt, __match_devt);
	if (dev) {
		put_device(dev);
		device_unregister(dev);
	}
}

7.3、示例代码

#include 
#include 
#include 
#include 
#include 

static int major = 230;
static int minor = 0;
static dev_t devno;
static struct class *cls = NULL;
static struct device *class_dev = NULL;
static int hello_open(struct inode *inode, struct file *file)
{
	printk("hello_open \n");
	return 0;
}

static int hello_release(struct inode *inode, struct file *file)
{
	printk("hello_release \n");
	return 0;
}

static struct file_operations fops = {
	.open = hello_open,
	.release = hello_release,
};
static int hello_init(void)
{
	int ret;
	printk("hello_init() \n");
	ret = register_chrdev(major, "hello_test", &fops);

	if(ret < 0)
	{
		printk("register_chrdev() file\n");
		return ret;
	}

	cls = class_create(THIS_MODULE,"hello_cls");
	if (IS_ERR(cls )) {
		ret = PTR_ERR(cls );
		goto out_err_0;
	}
	devno = MKDEV(major, minor);
	class_dev = device_create(cls, NULL, devno, NULL,"hello_dev");
	if (IS_ERR(class_dev)) {
		printk("device_create failed\n");
		ret = PTR_ERR(class_dev);
		goto out_err_1;
	}
	return 0;
out_err_1:
	class_destroy(cls);
out_err_0:
	unregister_chrdev(major, "hello_test");
	return ret;

}
static void hello_exit(void)
{
	printk("hello_exit() \n");
	device_destroy(cls,devno);
	class_destroy(cls);
	unregister_chrdev(major, "hello_test");
	return ;
}

MODULE_LICENSE("GPL");
module_init(hello_init);
module_exit(hello_exit);

你可能感兴趣的:(linux驱动,linux)