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来执行,这无疑更方便。

相关推荐
Ivanqhz几秒前
MLA、DSA、CSA、HCA
人工智能·算法·机器学习
菜_小_白33 分钟前
codex
linux·vscode·ai
zhangrelay43 分钟前
用ROS2Lyrical实验报告册思路重做蓝桥云课ROS1实验并改进
linux·笔记·学习·ubuntu·机器人
林兴洋1 小时前
linux-mtr命令-ping和traceroute的能力合二为一
linux
嘎嘎风1 小时前
MiniMind 学习笔记之 07 模型怎么学会猜词(旋钮是怎么被拧动的)
算法·源码阅读
OsDepK1 小时前
OSMDE_v1.9.0已加入FTP与shell功能
linux·运维·服务器
和裕1 小时前
定制纸箱刀模费全解析:费用定义与可减免合作场景
大数据·运维·网络·人工智能·算法
白山编程大哥1 小时前
C语言篇:语法进阶
c语言·数据结构·算法
硅基手札2 小时前
【Linux内核专栏 11】驱动框架:platform / char / misc / 设备树
linux·运维·服务器
Doubbbbbbble云2 小时前
基于流处理框架的实时算法实现策略4
算法