我目前正在研究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
复制相似问题