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

相关推荐
zhangfeng11333 小时前
AI编程范式:从Vibe Coding(氛围编程)向SDD规范驱动开发演进全解析
人工智能·驱动开发·ai编程
进击切图仔3 小时前
在 windows 和 ubuntu 中配置 host 文件
linux·windows·ubuntu
JNX_SEMI3 小时前
Hi5000Q/H 6.5~75V宽输入——与H5227A完全对等,无缝适配现有电源方案-聚能芯-智芯官方授权一级代理
驱动开发·单片机·嵌入式硬件·物联网·硬件工程
郭涤生3 小时前
C++ 零拷贝(Zero-Copy)
linux·开发语言·c++
weixin_445476683 小时前
LIMS 3.0 测试环境部署过程记录
linux·状态模式
The Chosen One9853 小时前
【操作系统】操作系统引导、虚拟机、进程通信、信号
linux·运维·服务器·操作系统·虚拟机·信号
宵时待雨3 小时前
linux笔记归纳14:Socket编程TCP
linux·服务器·网络·笔记·tcp/ip
饼饼学习空间智能3 小时前
遥操作数据能否提升机器人自主化水平?详解模仿学习、仿真放大与Sim2Real闭环
人工智能·算法
小张同学a.4 小时前
zabbix企业级监控平台3——服务监控与API实战
linux·运维·mysql·nginx·tomcat·zabbix
hwx15464 小时前
Linux内核时钟
linux