Rob*_*nes 17 kernel-module linux-device-driver linux-kernel
我正在阅读LKMPG(参见第4.1.4节.取消注册设备),我不清楚何时使用这些try_module_get / module_put功能.一些LKMPG示例使用它们,有些则不使用它们.
更令人困惑的是,try_module_get在2.6.24源代码的193个文件中出现了282次,但在Linux设备驱动程序(LDD3)和Essential Linux设备驱动程序中,它们甚至没有出现在单个代码示例中.
我想也许它们与旧register_chrdev接口绑定(由cdev接口取代2.6),但它们只出现在同一个文件中8次:
find -type f -name *.c | xargs grep -l try_module_get | sort -u | xargs grep -l register_chrdev | sort -u | grep -c .
Run Code Online (Sandbox Code Playgroud)
那么什么时候使用这些函数是合适的,它们是否与特定接口或一组环境的使用联系在一起?
编辑
我从LKMPG 加载了sched.c示例并尝试了以下实验:
anon@anon:~/kernel-source/lkmpg/2.6.24$ tail /proc/sched -f &
Timer called 5041 times so far
[1] 14594
anon@anon:~$ lsmod | grep sched
sched 2868 1
anon@anon:~$ sudo rmmod sched
ERROR: Module sched is in use
Run Code Online (Sandbox Code Playgroud)
这让我相信内核现在可以自己进行计算,而获取/放置可能已经过时了.任何人都可以验证吗?
Rol*_*and 18
你基本上不应该使用try_module_get(THIS_MODULE); 几乎所有这些用途都是不安全的,因为如果你已经在你的模块中,那么推迟引用计数就太晚了 - 总会有一个(小)窗口,你在模块中执行代码但是没有增加引用计数.如果有人在该窗口中完全删除了模块,那么您在卸载模块中运行代码的情况很糟糕.
您在LKMPG中链接的特定示例(其中代码在open()方法中执行try_module_get()将在现代内核中通过在struct file_operations中设置.owner字段来处理:
struct file_operations fops = {
.owner = THIS_MODULE,
.open = device_open,
//...
};
Run Code Online (Sandbox Code Playgroud)
这将使VFS代码在调用之前获取对模块的引用,这消除了不安全的窗口 - 在调用.open()之前try_module_get()将成功,或者try_module_get()将失败并且VFS永远不会打电话给模块.在任何一种情况下,我们都不会从已经卸载的模块中运行代码.
使用try_module_get()的唯一好处是,当您想要在调用它之前对其他模块进行引用或以某种方式使用它时(例如,我在上面解释的示例中执行文件打开代码).try_module_get(THIS_MODULE)在内核源代码中有很多用途,但大多数(如果不是全部)都是应该清理的潜在错误.
你无法卸载sched示例的原因是你的
$ tail /proc/sched -f &
Run Code Online (Sandbox Code Playgroud)
命令保持/ proc/sched打开,因为
Our_Proc_File->owner = THIS_MODULE;
Run Code Online (Sandbox Code Playgroud)
在sched.c代码中,打开/ proc/sched会增加sched模块的引用计数,它会占lsmod显示的1引用.从快速浏览其余代码开始,我认为如果你通过查杀tail命令来释放/ proc/sched,你就可以删除sched模块.