Memory management linux内核模块内存管理

Memory management linux内核模块内存管理,memory-management,linux-kernel,kernel-module,Memory Management,Linux Kernel,Kernel Module,我正在linux内核模块中试验内存管理,我想知道为什么线程不能看到与模块函数相同的内存。我的意思是 我全局声明了一个int*x。我使用kmalloc分配空间,并将10分配给它。现在,当我尝试从线程中访问它时,我得到了一个完全不同的值 为什么会发生这种情况?我怎样才能避开这件事 编辑: 我在x86体系结构中在单个内核(VM)上运行我的程序 以下是我的代码:在SMP体系结构上,缓存的值不会跨所有核心更新,因此另一个核心上的线程可以使用过时的值 您可能遇到的另一个问题是线程之间的并发访问,这意味着线程

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

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

为什么会发生这种情况?我怎样才能避开这件事

编辑:

我在x86体系结构中在单个内核(VM)上运行我的程序


以下是我的代码:

在SMP体系结构上,缓存的值不会跨所有核心更新,因此另一个核心上的线程可以使用过时的值

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

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

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


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

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

在SMP内核上,实现了一些锁机制(针对内核)来解决这一问题:

阅读
尤其是“CPU间锁定屏障效应”

您运行的是什么体系结构?我不相信其他答案说你遇到了内存排序问题或缓存一致性问题,因为

  • x86的顺序非常严格,而且
    kthread\u run()
    内部占用了大量锁等。因此,我确信在*x的赋值和线程的开始之间存在着相当于内存的障碍。因此,即使是在更弱有序的体系结构上,我也不认为您真的缺少内存障碍
  • 我不相信在Linux运行的体系结构中,CPU之间的缓存是不一致的。您必须小心外部设备在内存中进行DMA,但这与这里的问题完全不同
换句话说,我认为您在问题中编写的代码看起来不错。我怀疑这是从你的真实代码中提炼出来的,这样你就摆脱了真正的bug


确实,如果您的代码在
kthread\u运行之后修改了线程中使用的变量,那么您就有了一个争用条件,这可能会导致像您在这里看到的那样的错误。

感谢您的回复。该值不是由线程设置的,而是由module init函数完成的。我更新了问题,显示了一些代码。我将检查volatile是否有任何作用。它得到的值是多少而不是10?所以看起来我的第一个猜测是正确的。kthread_run正在另一个CPU或内核上删除该线程,并且缓存的x值不同。看看KarlP的答案。这里有更多:-)@KarlP我知道你通常不想使用volatile,除非它是基于微控制器的东西(实际上是我唯一使用它们的地方)。这是我想到的最简单的一件事。谢谢你的链接——它确实让我更了解它。但我现在不知道如何解决我的问题。为什么会这样?是因为无序执行吗?是因为无序执行和缓存。所以发生的事情是,内存访问被重新排序,将int*x缓存到某个随机值,该值由它在内存中的加载位置决定。您可以在另一个内核上更改该值,然后当您的线程使用过时的缓存值执行其任务时。为了修复它,我们使CPU使包含int*x的缓存失效,并读取更当前的值。有趣的是。但我展示的几乎是我所有的节目。我已经编辑了这个问题,并链接到了我的整个程序。此外,我还发现如果在此之后创建另一个线程,该线程的输出是10!奇怪。你的代码不是为我构建的(我需要
#include
来获得
kmalloc
的声明),但一旦我修复了它,它就会在真实系统(运行内核版本3.0)上打印
mem\u test:thread:value 10
。不确定你的bug可能是什么。我看到我的答案是关于内存障碍的空谈,而我实际上是建议使用锁(这也将实现mb)