我正在阅读LKMPG(See Section 4.1.4. Unregistering A Device),尚不清楚何时使用try_module_get / module_put函数。 LKMPG的一些示例使用它们,有些则不使用。

更令人困惑的是,try_module_get在2.6.24源文件的193个文件中出现282次,但是在Linux Device Drivers ( LDD3 )Essential Linux Device Drivers中,它们甚至没有出现在单个代码示例中。

我以为它们可能与旧的register_chrdev接口(interface)(由cdev接口(interface)在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 .

那么什么时候才适合使用这些功能,并将它们与特定接口(interface)或特定情况的使用联系在一起?

编辑

我从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

这使我相信内核现在执行自己的会计,并且取/放可能已过时。有人可以验证吗?

最佳答案

基本上,您永远不必使用try_module_get(THIS_MODULE);几乎所有这些用法都是不安全的,因为如果您已经在模块中,那么增加引用计数就为时已晚–总是会有一个(小)窗口,您可以在其中执行模块中的代码,但没有增加引用计数。如果有人完全在该窗口中删除了模块,那么您将处于在已卸载模块中运行代码的糟糕境地。

在LKMPG中链接的特定示例,其中代码在open()方法中执行try_module_get()的代码将在现代内核中通过在struct file_operations中设置.owner字段来处理:

struct file_operations fops = {
        .owner = THIS_MODULE,
        .open = device_open,
        //...
};

这将使VFS代码在调用模块之前先对其进行引用,从而消除了不安全的窗口-try_module_get()将在调用.open()之前成功,或者try_module_get()将失败并且VFS永远不会调用该模块。无论哪种情况,我们都永远不会从已经卸载的模块中运行代码。

使用try_module_get()的唯一好时机是当您想要在调用另一个模块或以某种方式使用它之前在另一个模块上进行引用时(例如,正如我在上面解释的示例中的文件打开代码所做的那样)。内核源代码中有很多try_module_get(THIS_MODULE)用途,但大多数(如果不是全部的话)都是应该清除的潜在错误。

您无法卸载计划的示例的原因是,您的
$ tail /proc/sched -f &

该命令使/ proc / sched打开,并且由于
        Our_Proc_File->owner = THIS_MODULE;

在sched.c代码中,打开/ proc / sched会增加sched模块的引用计数,这说明了lsmod显示的1个引用。快速浏览一下其余代码,我想如果您通过杀死tail命令来释放/ proc / sched,则可以删除sched模块。

关于linux-kernel - Linux内核模块:何时使用try_module_get/module_put,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1741415/

10-11 22:53
查看更多