/dev/目录下字符设备文件创建流程

device_add函数

在这里插入图片描述
1.首先,函数对传入的设备指针进行检查并获取设备的引用计数。如果设备不存在(指针为空),则跳转到done标签处,表示处理完成。如果设备的parent成员存在,函数会获取父设备的引用。然后,它使用父设备和当前设备作为参数,获取用于设备内核对象的父内核对象。
2.如果当前设备没有分配设备号(dev->devt中的主设备号),则不进行设备节点(devtmpfs)的创建。如果有设备号,则会创建设备文件和设备节点。其中调用device_create_file函数创建设备文件,将设备属性添加到/sys/devices目录下。调用device_create_sys_dev_entry函数创建设备节点,将设备添加到/dev目录下。调用devtmpfs_create_node函数创建设备节点,将设备添加到/devtmpfs目录下。
3.接下来,函数会通知与设备相关的总线(bus)和平台(platform)设备的注册。如果存在错误,将跳转到相应的错误处理标签。这部分代码调用device_platform_notify函数通知平台设备,即设备的驱动程序,该设备已经添加到系统中。
4.然后,函数会为设备添加属性文件、符号链接和类别(class)相关的节点。如果存在错误,将跳转到相应的错误处理标签。这部分代码调用device_create_file函数为设备添加属性文件,例如uevent文件用于设备的热插拔事件通知。然后,调用device_add_class_symlinks函数为设备添加类别相关的符号链接,将设备添加到类别的设备目录中。最后,调用device_add_attrs函数为设备添加其他属性。
5.接着,函数会向设备电源管理子系统注册设备,并将设备添加到总线中。如果存在错误,将跳转到相应的错误处理标签。这部分代码调用dpm_sysfs_add函数将设备添加到设备电源管理子系统中,以进行设备电源管理的操作。然后,调用device_pm_add函数将设备添加到总线中,以便进行总线相关的操作。
6.若设备已分配父设备并且父设备存在,函数会将当前设备添加到父设备的子设备链表中。这部分代码检查当前设备是否有父设备,并且父设备存在。如果满足条件,将当前设备添加到父设备的子设备链表中,以便进行层次关系的管理。
7.如果当前设备有关联的类别(class),函数会将设备添加到类别的设备链表中,并通知类别相关的接口设备已添加。这部分代码调用device_add_class_device函数将设备添加到类别的设备链表中,以便进行类别相关的管理操作。然后,调用class_find_device函数查找设备链表中是否存在相同的设备,如果存在则将设备移动到找到的设备的位置。

devtmpfs_create_node函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
后台会创建kdevtmpfs内核线程进行/dev/目录下文件的创建。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

filename_create函数

在这里插入图片描述
在kern_path_create->filename_create函数中最终会创建文件。
在这里插入图片描述

filename_parentat函数的功能是在指定的目录中获取给定路径的父目录的路径对象。
dfd:父目录的文件描述符。
name:要获取父目录的路径的路径名。
flags:查找标志位。
parent:用于存储父目录的路径对象。
last:用于存储路径中最后一个组件的qstr结构。
type:用于存储路径中最后一个组件的类型。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在path_init函数中由于最开始dentry = kern_path_create(AT_FDCWD, nodename, &path, 0);所以在调用get_fs_pwd(current->fs, &nd->path);函数时会将nd->path赋值为current->fs->pwd。

在这里插入图片描述
在这里插入图片描述
而在最开始初始化devtmpfs_setup函数中会首先调用init_mount函数将devtmpfs文件系统挂载到根目录"/“上,使用文件系统类型"devtmpfs”,挂载选项MS_SILENT,并不传递额外的挂载数据(NULL)。然后,调用init_chdir函数,将当前进程的工作目录设置为"/…",即根目录。

继续上文在filename_create函数中最终会有dentry = __lookup_hash(&last, path->dentry, lookup_flags);其中设置了标志位LOOKUP_CREATE | LOOKUP_EXCL即在没找到目录时创建该目录。
函数__lookup_hash功能是在指定的目录中查找指定名称的目录项(文件或子目录)
name:要查找的目录项的名称。
base:要查找的目录的根目录项。
flags:查找标志位。

在这里插入图片描述
如何调用vfs_mknod函数在指定的目录中创建一个新的特殊文件节点(设备节点)。
dir:指向父目录的inode结构指针,表示新节点将被创建在该目录下。
dentry:指向新节点的目录项(dentry)的指针,包含了新节点的名称。
mode:新节点的权限和类型模式,包括文件类型和访问权限等信息。
dev:新节点的设备号,用于标识特殊文件节点的设备。

ramfs_init_fs_context文件系统

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在ramfs文件系统中操作函数ramfs_mknod->ramfs_get_inode中对于不同的mode类型进行不同的处理。如S_IFDIR目录文件,则设置inode->i_op = &ramfs_dir_inode_operations;inode->i_fop = &simple_dir_operations;。对于普通文件则调用init_special_inode进行设置。

在这里插入图片描述
在devtmpfs_create_node函数进行任务提交时,如果不是块设备就会设置为S_IFCHR字符设备。

在这里插入图片描述
对于字符设备会将操作函数设置def_chr_fops,后续将进一步展开描述字符设备def_chr_fops的实现原理。

总结

1.字符设备文件(/dev/)是Linux系统中用于管理字符设备的特殊目录,应用程序可以通过打开和读写该目录下的文件节点与字符设备进行通信。
2.device_add函数是Linux内核中用于向系统添加设备的函数,它将设备添加到设备层次结构中,并进行资源分配和数据结构初始化,以便内核和驱动程序管理设备。
3.devtmpfs是一个临时文件系统,用于在系统启动时自动创建和管理设备节点。它为字符设备和块设备分配设备号,并与驱动程序建立连接,使得设备能够被应用程序访问和操作。
4.字符设备文件、device_add函数和devtmpfs文件系统之间的关系是:应用程序通过字符设备文件与设备进行通信,device_add函数将设备添加到系统中,而devtmpfs文件系统在系统启动时负责创建和管理字符设备节点,为设备提供临时的文件系统支持。这三者共同构成了Linux系统中字符设备管理的基础。

  • 31
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设备驱动程序在`/dev`目录创建设备文件节点,可以使用`unlink()`函数删除。具体的做法是,在驱动程序的`module_exit()`函数中调用`unlink()`函数,删除设备节点对应的设备文件。例如: ```c #include <linux/module.h> #include <linux/fs.h> #include <linux/device.h> static dev_t dev_num; // 设备号 static struct class *dev_class; // 设备类 static struct device *dev; // 设备对象 static int __init my_driver_init(void) { // 分配设备号 if (alloc_chrdev_region(&dev_num, 0, 1, "my_driver") < 0) { printk(KERN_ERR "Failed to allocate device number\n"); return -1; } // 创建设备dev_class = class_create(THIS_MODULE, "my_driver_class"); if (IS_ERR(dev_class)) { unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to create device class\n"); return -1; } // 创建设备对象 dev = device_create(dev_class, NULL, dev_num, NULL, "my_device"); if (IS_ERR(dev)) { class_destroy(dev_class); unregister_chrdev_region(dev_num, 1); printk(KERN_ERR "Failed to create device object\n"); return -1; } // 其他初始化操作... return 0; } static void __exit my_driver_exit(void) { // 其他清理操作... // 删除设备对象 device_destroy(dev_class, dev_num); // 删除设备类 class_destroy(dev_class); // 释放设备号 unregister_chrdev_region(dev_num, 1); // 删除设备文件 unlink("/dev/my_device"); } module_init(my_driver_init); module_exit(my_driver_exit); ``` 在驱动程序的`module_exit()`函数中,先调用`device_destroy()`函数和`class_destroy()`函数,释放设备对象和设备类,然后调用`unregister_chrdev_region()`函数,释放设备号。最后调用`unlink()`函数,删除设备文件。需要注意的是,删除设备文件需要具有相应的权限,否则会返回错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值