【问题标题】:linux kernel module memory managementlinux内核模块内存管理
【发布时间】:2011-11-29 13:50:59
【问题描述】:

我正在尝试在 linux 内核模块中进行内存管理,我想知道为什么线程看不到与模块函数相同的内存。我的意思是,

我有一个全局声明的int *x。我使用 kmalloc 分配空间并为其分配 10。现在,当我尝试从线程中访问它时,我得到了完全不同的值。

为什么会这样?我该如何解决这个问题?

编辑:

我在 x86 架构中在单核(在 VM 上)上运行我的程序。

这是我的代码:http://pastebin.com/94qGc6ZQ

【问题讨论】:

    标签: memory-management linux-kernel kernel-module


    【解决方案1】:

    在 SMP 架构上,缓存的值不会在所有内核上更新,因此另一个内核上的线程可能会使用过时的值。

    您可能遇到的另一个问题是线程之间的并发访问,这意味着线程 1 在线程 2 能够写入 x 之前读取 x,但线程 2 继续说 x = 10,但是当 x 未初始化时,线程 1 仍在使用旧值。

    解决第二个问题(似乎更有可能)的方法是使用锁定来控制对该变量的访问,这样一次只有 1 个线程可以修改/读取它以避免过时值的问题。

    (不是硬件内核模块,所以不要使用 volatile ;P)使用下面 smp_wb 和 smp_rb 的建议。

    编辑:看起来我的第一个建议是正确的。因此,要解决这个问题,您可以在执行 kmalloc 和分配之前在 x 上使用 smp_wb。然后在尝试打印 x 的值之前在 x 上设置一个读取屏障。这有效地告诉 CPU 读取新值,因为它可能是坏的或者可能在访问中被重新排序。您可能只能在另一个线程上使用读取屏障,但为了安全,请在访问完成时使用屏障。

    【讨论】:

    • 感谢您的回复。该值不是由线程设置的,它是由模块初始化函数完成的。我已经更新了显示一些代码的问题。我会检查 volatile 是否有任何作用。
    • 得到什么值而不是 10?
    • 看来我的第一个猜测是正确的。 kthread_run 正在将该线程丢弃到另一个 CPU 或内核上,并且缓存具有不同的 x 值。看看 KarlP 的回答。
    • @KarlP 我知道你通常不想使用 volatile,除非它是基于微控制器的东西(真的是我唯一使用它们的地方)。只是想到的最简单的事情。
    【解决方案2】:

    您需要某种锁(以及使缓存无效的内存屏障。)

    在 SMP 内核上,实现了(用于内核的)锁定机制来处理这个问题:

    阅读http://www.mjmwired.net/kernel/Documentation/memory-barriers.txt 尤其是“CPU 间锁定屏障效应”

    【讨论】:

    • 感谢该链接 - 它确实帮助我更多地理解它。但我现在不确定如何解决我的问题。为什么会发生?是因为乱序执行吗?
    • 发生这种情况是因为乱序执行和缓存。所以发生的事情是内存访问以一种将 int *x 缓存到某个随机值的方式重新排序,该随机值由它在内存中的加载位置确定。您在另一个核心上更改该值,然后当您的线程使用过时的缓存值执行它时。为了解决这个问题,我们让 CPU 使包含 int *x 的缓存无效并读入一个更当前的值。
    【解决方案3】:

    您在什么架构上运行?我不相信其他说您遇到内存排序问题或缓存一致性问题的答案,因为

    • x86 的顺序非常严格,kthread_run() 内部占用了很多锁等,我敢肯定在分配给 *x 和线程开始之间存在等效的内存屏障。因此,即使在更弱排序的架构上,我也不认为您真的缺少内存屏障。
    • 我不相信有 任何 架构在其中运行 Linux 的 CPU 之间的缓存不连贯。您必须小心使用 DMA 进入内存的外部设备,但这与这里的问题完全不同。

    换句话说,我认为您在问题中编写的代码看起来不错。我怀疑这是从你的真实代码中总结出来的,这样你就摆脱了真正的错误。

    确实,如果您有修改线程中使用的变量的代码 kthread_run 之后,那么您就有可能导致像您在此处看到的错误的竞争条件。

    【讨论】:

    • 有趣。但我所展示的几乎是我的所有程序。我已经用指向我的整个程序的链接编辑了这个问题。另外,我发现如果我在此之后创建另一个线程,线程的输出是 10!奇怪。
    • 你的代码不是为我构建的(我需要#include <linux/slab.h> 来获得kmalloc 的声明)但是一旦我修复了它,它就会在真实系统上打印mem_test: thread: value 10(运行内核版本3.0)。不确定您的错误可能是什么。
    • +1:是的。当我真的建议一个锁(这也将实现一个 mb)时,我看到我的答案是关于内存障碍的喋喋不休
    猜你喜欢
    • 1970-01-01
    • 2020-06-13
    • 2014-06-01
    • 2012-04-11
    • 2013-12-17
    • 1970-01-01
    • 2015-10-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多