linux内核中内存障碍的用途
Robert Love说,“set_task_state(任务,状态)将给定任务设置为给定状态。如果适用,它还提供了一个内存屏障,以强制在其他处理器上排序(这仅在SMP系统上需要),否则它相当于 任务->状态=状态 我的问题是: 内存障碍如何在其他处理器上强制排序 罗伯特·洛夫这样说是什么意思?为什么需要这样做? 他可能在说什么排序?他是在说安排队列吗 如果是,SMP中的每个处理器是否都有不同的调度队列?linux内核中内存障碍的用途,linux,linux-kernel,embedded-linux,Linux,Linux Kernel,Embedded Linux,Robert Love说,“set_task_state(任务,状态)将给定任务设置为给定状态。如果适用,它还提供了一个内存屏障,以强制在其他处理器上排序(这仅在SMP系统上需要),否则它相当于 任务->状态=状态 我的问题是: 内存障碍如何在其他处理器上强制排序 罗伯特·洛夫这样说是什么意思?为什么需要这样做? 他可能在说什么排序?他是在说安排队列吗 如果是,SMP中的每个处理器是否都有不同的调度队列? 我很困惑为了挤出额外的性能,您的CPU会这样做,这可能会以不同于代码中给定的顺序运行操作。
我很困惑为了挤出额外的性能,您的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执行大量无序执行:它们一次加载许多指令,如果它们之间没有依赖关系,则以不确定的顺序执行 <>为了避免编译器优化导致的重新排序,
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();