21

我正在阅读 LKMPG(请参阅第 4.1.4 节。取消注册设备),我不清楚何时使用这些try_module_get / module_put功能。一些 LKMPG 示例使用它们,有些则没有。

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

我想也许它们与旧register_chrdev接口相关联(在 2.6 中被 cdev 接口取代),但它们只一起出现在同一个文件中 8 次:

find -type f -name *.c | xargs grep -l try_module_get | sort -u | xargs grep -l register_chrdev | sort -u | grep -c .

那么什么时候适合使用这些功能,它们是否与特定界面或一组环境的使用相关联?

编辑

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

这让我相信内核现在自己做账,gets/puts可能已经过时了。任何人都可以验证这一点吗?

4

1 回答 1

22

您基本上不应该使用 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) 的用法,但如果不是全部的话,大多数都是应该清理的潜在错误。

您无法卸载 sched 示例的原因是您的

$ tail /proc/sched -f &

命令保持 /proc/sched 打开,并且因为

        Our_Proc_File->owner = THIS_MODULE;

在 sched.c 代码中,打开 /proc/sched 会增加 sched 模块的引用计数,这说明 lsmod 显示的 1 个引用。通过快速浏览其余代码,我认为如果您通过终止 tail 命令释放 /proc/sched,您将能够删除 sched 模块。

于 2011-05-21T05:32:56.880 回答