Johannes 《Linux内核模块与设备驱动开发:编写Linux驱动程序》 (10)auto_devfile

复制代码
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/cdev.h>

static dev_t dev_nr;
static struct cdev my_cdev;
static struct class *my_class;

static ssize_t my_read(struct file *f, char __user *u, size_t l, loff_t *o)
{
	pr_info("hello_cdev - Read is called\n");
	return 0;
}


static struct file_operations fops = {
	.read = my_read
};

static int __init my_init(void)
{
	int status;
#ifdef STATIC_DEVNR
	dev_nr = STATIC_DEVNR;
	status = register_chrdev_region(dev_nr, MINORMASK + 1, "hello_cdev");
#else
	status = alloc_chrdev_region(&dev_nr, 0, MINORMASK + 1, "hello_cdev");
#endif
	if (status) {
		pr_err("hello_cdev - Error reserving the region of device numbers\n");
		return status;
	}

	cdev_init(&my_cdev, &fops);
	my_cdev.owner = THIS_MODULE;

	status = cdev_add(&my_cdev, dev_nr, MINORMASK + 1);
	if (status) {
		pr_err("hello_cdev - Error adding cdev\n");
		goto free_devnr;
	}

	pr_info("hello_cdev - Registered a character device for Major %d starting with Minor %d\n", MAJOR(dev_nr), MINOR(dev_nr));

	my_class = class_create("my_class");
	if (!my_class) {
		pr_err("hello_cdev - Could not create class my_class\n");
		status = ENOMEM;
		goto delete_cdev;
	}

	if (!device_create(my_class, NULL, dev_nr, NULL, "hello%d", 0)) {
		pr_err("hello_cdev - Could not create device hello0\n");
		status = ENOMEM;
		goto delete_class;
	}

	pr_info("hello_cdev - Created device under /sys/class/my_class/hello0\n");

	return 0;

delete_class:
	class_unregister(my_class);
	class_destroy(my_class);
delete_cdev:
	cdev_del(&my_cdev);
free_devnr:
	unregister_chrdev_region(dev_nr, MINORMASK + 1);
	return status;
}

static void __exit my_exit(void)
{
	device_destroy(my_class, dev_nr);
	class_unregister(my_class);
	class_destroy(my_class);
	cdev_del(&my_cdev);
	unregister_chrdev_region(dev_nr, MINORMASK + 1);
}

module_init(my_init);
module_exit(my_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Johannes 4Linux");
MODULE_DESCRIPTION("A sample driver for manually registering a character device");

和lesson9 相比就添加了如下代码:

static struct class *my_class;

添加了一个叫my_class 的静态结构。class 在c++中很常见,有公有私有保护数据(public/private/protected),但是c里面是没有类这个数据结构的,在c中最类似的是结构(strcut),但是struct 中都是公有数据。这里等于C++中给了一个全局变量的公共类。

my_class = class_create("my_class");

if (!my_class) {

pr_err("hello_cdev - Could not create class my_class\n");

status = ENOMEM;

goto delete_cdev;

}

if (!device_create(my_class, NULL, dev_nr, NULL, "hello%d", 0)) {

pr_err("hello_cdev - Could not create device hello0\n");

status = ENOMEM;

goto delete_class;

}

class_create():

dynamically creates a device class in the Linux kernel, allowing automatic management of device nodes and integration with sysfs.

device_create():

To create a device in Linux using the device_create function, follow these steps:

  • Include the necessary header file in your kernel module:#include <linux/device.h>

  • Ensure that a class has been created using the class_create function. This class will be associated with the device:

my_class = class_create("my_class");

  • Use the device_create function to dynamically create the device: struct device *my_device = device_create(my_class, NULL, dev_t, NULL, "device_name"); Replace my_class with the pointer to your class. Use NULL for the parent device if there is no parent. Provide the dev_t (device number) for the device. Use NULL for driver-specific data if not needed. Specify the name of the device (e.g., "device_name").
  • Verify that the device is successfully created by checking the return value of device_create . It should return a valid pointer to the struct device:

if (!device_create(my_class, NULL, dev_nr, NULL, "hello%d", 0)) {

pr_err("hello_cdev - Could not create device hello0\n");

status = ENOMEM;

goto delete_class;

}

  • The device will now appear in /sys/devices/virtual and /dev directories.

这样在device_create()/class_create()之后就直接添加了设备,不需要mknod来执行,这无疑更方便。

相关推荐
赵民勇24 分钟前
systemd-sysusers命令详解
linux·运维
灿烂的贝壳24 分钟前
FC SAN多路径负载均衡配置指南
linux
余额瞒着我当琳27 分钟前
C++多态深入解析:多态概念,多态实现条件,虚函数表与内存分布,常见问题及注意事项
c++·算法
binqian32 分钟前
【Linux】内核怎么管理侦听socket
linux·网络协议
维克兜率天35 分钟前
【维克】模块3总结:从一行空数据,到一个能跑的模型
python·深度学习·算法
j7~37 分钟前
【Linux网络】三十七.TCP 协议通讯流程
linux·网络编程·三次握手·四次挥手·tcp 协议通讯流程
飞Link39 分钟前
定积分理论与 Python 仿真完全指南
python·算法
顶点多余1 小时前
9.15 面试问题总结(一面挂)
linux·面试·职场和发展
顺风尿一寸1 小时前
从 ls -U 到 Tomcat libs加载jar包:ext4 目录哈希序如何影响 Java 文件排序顺序
linux·jvm