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

查看:143
本文介绍了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接口绑定(由cdev接口在2.6中取代),但它们在同一文件中仅出现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

这使我相信内核现在可以自己进行记帐了,获取/认沽权可能已经过时了.有人可以验证吗?

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.

您无法卸载计划的示例的原因是您的

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天全站免登陆