我目前正在研究Linux设备驱动程序,并混淆了两个类似的静态设备注册函数:
register_chrdev()register_chrdev_region()这些功能都是静态注册设备驱动程序的。第一功能注册单个设备驱动程序,而后者注册一系列设备驱动程序。
让我困惑的是,一个设备驱动程序可以处理对同一设备的许多实例的访问。因此,对于给定的设备类型,应该只注册一个设备驱动程序。然后,多个设备可以通过多个mknod调用引用此驱动程序。
那么我的问题是,这两种功能在使用上有什么区别呢?
发布于 2022-04-14 17:00:44
struct file_operations *fops被分配给一个struct cdev,它是现代Linux中访问字符设备的机制的一部分(实际上是从内核版本2.5.70开始)。register_chrdev()早于struct cdev的引入,并代表调用方在内部分配struct cdev。这个struct cdev将通过调用匹配的注销注册函数unregister_chrdev()来解除分配。__register_chrdev()类似于register_chrdev(),但允许指定次要设备的基本小数和计数(register_chrdev(major, name, fops)等同于__register_chrdev(major, 0, 256, name, fops))。匹配的注销注册函数是__unregister_chrdev()。
register_chrdev_region()是最近的,它期望调用者自己管理struct cdev对象。有两种常见的模式:一个struct cdev用于register_chrdev_region()注册的整个dev_t值,或者在驱动程序的probe函数设置设备时根据需要为单个dev_t值动态创建struct cdev。( dev_t值是主设备号和次要设备号的组合。)
alloc_chrdev_region()与register_chrdev_region()相似,但总是动态地选择主设备号。
register_chrdev_region()和alloc_chrdev_region()的匹配注销函数是unregister_chrdev_region()。
在内部,上面的alloc_、register_和__register_函数调用__register_chrdev_region()来保留dev_t值的范围,而上面的unregister_和__unregister函数调用__unregister_chrdev_region()来释放保留的dev_t值。(__register_chrdev_region()和__unregister_chrdev_region()是内部函数,在“fs/char_dev.c”之外没有外部链接)。
使用较新接口的代码需要cdev_alloc()来分配struct cdev或cdev_init()来初始化现有的、尚未初始化的struct cdev。(cdev_init()还将struct cdev的ops成员设置为提供的文件操作指针。cdev_alloc()的调用者需要将文件操作指针分配给ops成员本身。)函数cdev_add()将struct cdev绑定到以前由register_chrdev_region()或alloc_chrdev_region()注册的一个或多个dev_t值的范围。cdev_del()取消cdev_add()的效果,并/或释放由cdev_alloc()分配的struct cdev。
https://stackoverflow.com/questions/71835899
复制相似问题