linux内核中内存障碍的用途

linux内核中内存障碍的用途,linux,linux-kernel,embedded-linux,Linux,Linux Kernel,Embedded Linux,Robert Love说,“set_task_state(任务,状态)将给定任务设置为给定状态。如果适用,它还提供了一个内存屏障,以强制在其他处理器上排序(这仅在SMP系统上需要),否则它相当于 任务->状态=状态 我的问题是: 内存障碍如何在其他处理器上强制排序 罗伯特·洛夫这样说是什么意思?为什么需要这样做? 他可能在说什么排序?他是在说安排队列吗 如果是,SMP中的每个处理器是否都有不同的调度队列? 我很困惑为了挤出额外的性能,您的CPU会这样做,这可能会以不同于代码中给定的顺序运行操作。

Robert Love说,“set_task_state(任务,状态)将给定任务设置为给定状态。如果适用,它还提供了一个内存屏障,以强制在其他处理器上排序(这仅在SMP系统上需要),否则它相当于 任务->状态=状态

我的问题是: 内存障碍如何在其他处理器上强制排序

罗伯特·洛夫这样说是什么意思?为什么需要这样做? 他可能在说什么排序?他是在说安排队列吗

如果是,SMP中的每个处理器是否都有不同的调度队列?
我很困惑

为了挤出额外的性能,您的CPU会这样做,这可能会以不同于代码中给定的顺序运行操作。优化编译器可以更改操作顺序以加快代码速度。编译器编写者/内核类型必须注意不要更改预期(或者至少符合规范,这样他们就可以说你的期望不正确)

这里有一个例子

1: CPU1: task->state = someModifiedStuff
2: CPU1: changed = 1;
3: CPU2: if (changed)
4: CPU2:  ...
如果我们没有设置状态的障碍,我们可以重新排列1和2。 因为两个都没有引用另一个,所以单线程实现不会看到任何差异。但是,在SMP情况下,我们对1和2进行了重新排序。第3行可以看到更改,但不会看到状态更改。例如, 如果CPU1运行第2行(而不是第1行),然后CPU2运行第3行和第4行,则CPU2将以旧状态运行,如果随后清除更改,则CPU1刚才所做的更改将丢失

屏障告诉系统,在某个点上,在1和2之间,它必须使事情在继续之前保持一致


搜索一下“内存屏障”,你会发现一些不错的帖子:

内存屏障是必需的,因为当前的CPU执行大量无序执行:它们一次加载许多指令,如果它们之间没有依赖关系,则以不确定的顺序执行

<>为了避免编译器优化导致的重新排序,易挥发< /COD>关键字是足够的(这里讲C++)。所以,同步原语(例如,代码>锁< /代码>)是通过正确使用<代码> Value和某种汇编程序<代码> Stave实现的。(它们有很多,或多或少很强:见中的第7.5.5节)

你知道锁是什么吗

x = 0;

thread 1:                           thread 2:

a.lock();                           a.lock();
x++;                                x++;
a.unlock();                         a.unlock();
x
将正确执行
2
。现在假设这两个线程的指令的执行顺序没有保证。如果执行的指令是(a和x是独立的,因此如果
lock()
没有使用内存屏障正确执行,则允许无序执行)该怎么办:


x
的结果可能等于
2
1

抱歉这么天真。我不明白如何“重新排列1和2“会在这里引起问题吗?因为它们每个都是不同的-即使在SMP上也不会引起问题。在这种情况下,我写的或C程序中的所有代码都需要按顺序执行。(事实上的内存障碍).但现在,你说如果我需要在SMP的不同处理器中执行某个操作,它可以是线程。但我仍在试图理解执行顺序不同的场景。即使每个可执行语句都是独立的,也可能发生这种情况。不确定“CPU如何运行”知道它们是独立的还是相互依赖的。想象一下,计算三角形的斜边时,你需要加上c^2=a^2+b^2。如果你先将a平方,或者先将b平方,这两种顺序都可以,没问题。有些操作,如互斥体,需要屏障作为其正确性实现的一部分。其他要求不依赖:即你不能计算c^2,直到得到a^2和b^2。看一看,以回答您的另一个问题-是的,SMP系统中的每个CPU核都有自己的任务调度核。。。
x = 0;

thread 1:                           thread 2:

x++;                                x++;
a.lock();                           a.lock();
a.unlock();                         a.unlock();