Linux驱动开发之注册

原创
2017/09/12 20:05
阅读数 60

模块注册

你必须记住一件事, 在注册内核设备时, 注册可能失败,即便最简单的动作常常需要内存分配, 分配的内存可能不可用,因此模块代码必须一直检查返回值, 并且确认要求的操作实际上已经成功。

如果证实你的模块在一个特别类型的失败后完全不能加载, 你必须取消任何在失败前注册的动作。

错误恢复有时用 goto 语句处理是最好的。我们通常不愿使用 goto, 但是在我们的观念里, 这是一个它有用的地方。在错误情形下小心使用 goto 可以去掉大量的复杂, 过度对齐的"结构形" 的逻辑,因此在内核里goto 是处理错误经常用到。

模块清理函数必须撤销任何由初始化函数进行的注册, 并且惯例(但常常不是要求的)是按照注册时相反的顺序注销设施。

使代码重复最小和所有东西流线化, 你应当做的是无论何时发生错误都从初始化里调用清理函数,清理函数接着必须在撤销它的注册前检查每一项的状态。

注意清理函数当由非退出代码调用时不能标志为 __exit。

不要注册任何设备, 直到所有的需要支持那个设备的你的内部初始化已经完成。cdev_add 一返回, 你的设备就是"活的"并且内核可以调用它的操作。除非你的驱动完全准备好处理设备上的操作, 你不应当调用 cdev_add。

字符设备的注册,内核在内部使用类型 struct cdev 的结构来代表字符设备,在内核调用你的设备操作前, 你编写分配并注册一个或几个这些结构。

  • 分配和初始化:cdev_init(...)
  • 通知内核:cdev_add(...)
  • 去除:cdev_del(...)

模块参数

任何使用它们的细节见 moduleparam.h,所有的模块参数应当给定一个缺省值; insmod 只在用户明确告知它的时候才改变这些值。模块可检查明显的参数, 通过对应它们的缺省值检查这些参数。

最后的 module_param 字段是一个权限值,你应当使用 <linux/stat.h> 中定义的值,这个值控制谁可以存取这些模块参数在 sysfs 中的表示. 如果 perm 被设为 0, 就根本没有 sysfs 项。否则它出现在 /sys/module下面,带有给定的权限。使用 S_IRUGO 作为参数可以被所有人读取, 但是不能改变; S_IRUGO|S_IWUSR 允许 root 来改变参数。注意如果一个参数被 sysfs 修改, 你的模块看到的参数值也改变了, 但是你的模块没有任何其他的通知。你应当不要使模块参数可写, 除非你准备好检测这个改变并且因而作出反应。

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
在线直播报名
返回顶部
顶部