Linux 内核模块:何时使用 try_module_get/module_put [英] Linux Kernel Modules: When to use try_module_get / module_put

查看:17
本文介绍了Linux 内核模块:何时使用 try_module_get/module_put的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在阅读 LKMPG(参见第 4.1.4 节.注销设备 ),我不清楚何时使用 try_module_get/module_put 函数.一些 LKMPG 示例使用它们,一些不使用.

I was reading the LKMPG ( See Section 4.1.4. Unregistering A Device ) and it wasn't clear to me when to use the try_module_get / module_put functions. Some of the LKMPG examples use them, some don't.

更令人困惑的是,try_module_get 在 2.6.24 源代码的 193 个文件中出现了 282 次,但在 Linux 设备驱动程序 (LDD3)基本 Linux 设备驱动程序,它们出现甚至没有一个代码示例.

To add to the confusion, try_module_get appears 282 times in 193 files in the 2.6.24 source, yet in Linux Device Drivers ( LDD3 ) and Essential Linux Device Drivers, they appears in not even a single code example.

我以为它们可能与旧的 register_chrdev 接口有关(在 2.6 中被 cdev 接口取代),但它们只在同一个文件中一起出现 8 次:

I thought maybe they were tied to the old register_chrdev interface ( superseded in 2.6 by the cdev interface ), but they only appear together in the same files 8 times:

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

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

So when is it appropriate to use these functions and are they tied to the use of a particular interface or set of circumstances?

编辑

我从 LKMPG 加载了 sched.c 示例并尝试了以下实验:

I loaded the sched.c example from the LKMPG and tried the following experiment:

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 可能已经过时了.任何人都可以验证这一点吗?

This leads me to believe that the kernel now does it's own accounting and the gets / puts may be obsolete. Can anyone verify this?

推荐答案

本质上你不应该使用 try_module_get(THIS_MODULE);几乎所有这样的使用都是不安全的,因为如果你已经在你的模块中,那么增加引用计数就太晚了——总会有一个(小)窗口在你的模块中执行代码但没有增加引用数数.如果有人在该窗口中完全删除了模块,那么您将处于在卸载的模块中运行代码的糟糕情况.

You should essentially never have to use try_module_get(THIS_MODULE); pretty much all such uses are unsafe since if you are already in your module, it's too late to bump the reference count -- there will always be a (small) window where you are executing code in your module but haven't incremented the reference count. If someone removes the module exactly in that window, then you're in the bad situation of running code in an unloaded module.

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

The particular example you linked in LKMPG where the code does try_module_get() in the open() method would be handled in the modern kernel by setting the .owner field in struct file_operations:

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

这将使 VFS 代码在调用模块之前引用模块 ,从而消除不安全窗口——要么 try_module_get() 在调用 .open() 之前成功,否则 try_module_get() 将失败并且 VFS 将永远不会调用模块.无论哪种情况,我们都不会从已经卸载的模块中运行代码.

this will make the VFS code take a reference to the module before calling into it, which eliminates the unsafe window -- either the try_module_get() will succeed before the call to .open(), or the try_module_get() will fail and the VFS will never call into the module. In either case, we never run code from a module that has already been unloaded.

使用 try_module_get() 的唯一好时机是当您想在调用一个不同 模块之前引用它或以某种方式使用它(例如文件打开代码在我上面解释的例子).内核源代码中有许多 try_module_get(THIS_MODULE) 的用途,但大多数(如果不是全部)都是应该清理的潜在错误.

The only good time to use try_module_get() is when you want to take a reference on a different module before calling into it or using it in some way (eg as the file open code does in the example I explained above). There are a number of uses of try_module_get(THIS_MODULE) in the kernel source but most if not all of them are latent bugs that should be cleaned up.

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

The reason you were not able to unload the sched example is that your

$ tail /proc/sched -f &

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

command keeps /proc/sched open, and because of

        Our_Proc_File->owner = THIS_MODULE;

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

in the sched.c code, opening /proc/sched increments the reference count of the sched module, which accounts for the 1 reference that your lsmod shows. From a quick skim of the rest of the code, I think if you release /proc/sched by killing your tail command, you would be able to remove the sched module.

这篇关于Linux 内核模块:何时使用 try_module_get/module_put的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆