定制网站建设电话,WordPress开发微信支付,江西建设信息港网站,襄阳做网站比较有实力的公司前言
随着时间的推移#xff0c;共享内存已经在修真界已经沦为禁术。因为使用这种方式沟通的两人往往会陷入到走火入魔的状态#xff0c;思维扭曲。进程君父子见到这种情况#xff0c;连忙开始专研起来#xff0c;终于它们发现了共享内存存在的问题#xff1a;
进程间冲…前言
随着时间的推移共享内存已经在修真界已经沦为禁术。因为使用这种方式沟通的两人往往会陷入到走火入魔的状态思维扭曲。进程君父子见到这种情况连忙开始专研起来终于它们发现了共享内存存在的问题
进程间冲突
我们现在假设这样一种情况有三个进程它们使用共享内存完成通信。进程1向共享内存中写入一些数据想让进程2读取这些数据。很不巧由于缺乏管理现在进程3也同时在向共享内存中写入数据。进程1与进程3的数据发生了相互冲突与相互覆盖对于进程2来说读取到了一些无意义的数据。如下图所示这种相互冲突的问题是也是共享内存最大的局限性。如何解决不是我们这一节的重点我们下一节再讨论请大家继续向后看。 上面这种情况属于比较容易理解的范畴下面这个就比较抽象了。 现在假设一种情况我们在共享内存中定义了一个变量x初始值为0现在有两个进程同时对这个变量进行加一操作最后这个变量的值应该是多少 既然我都这么问了当然答案不可能是2实际上我们无法判断这个变量最终的值它可能是1也可能是2可能每次运行结果都不同。这种反直觉的现象是什么原因造成的呢接下来我带大家分析一下。 在c或者c中我们对一个变量x进行加一操作无非一下两种手段这里假设x已经被定义并且初始化为0。
// 方案1
x x 1;// 方案2
x;大家在上面看到的是两条语句因此可能想当然的认为这两条语句每条都是一次直接执行完毕。但是实际上对于这两条语句中的任意一条语句他的执行大概分为三步。我们先编写一段C语言代码。在这里为了模拟共享内存我们在全局区定义x并初始化为0模拟x在共享内存中的情况。
#include stdio.hint x 0;int main() {x x 1;return 0;
}
我们将这段代码进行汇编观察它的汇编代码如下所示根据#注释的内容我们可以看到main.c文件的第六行的xx1;对应着三条汇编语句它们分别是1把变量x从内存中转移到CPU寄存器eax中2在寄存器eax中对变量x加一3把处理后的变量x从寄存器中放回到内存中。
main:
.LFB0:# 进入main函数后需要压栈
# main.c:6: x x 1;movl x(%rip), %eax # x, x.0_1addl $1, %eax #, _2
# main.c:6: x x 1;movl %eax, x(%rip) # _2, x
# main.c:7: return 0;movl $0, %eax #, _5
# main.c:8: }# 即将离开main函数需要出栈ret .cfi_endproc每一条汇编指令都是原子的也就是不会被进程切换打断的。但是对于单核CPU在每两条汇编指令之间都有可能会发生进程的切换。对于多核CPU也可能会出现同时处理的情况这会造成什么影响呢我们用下面的图来表示
小结
今天我们详细分析了共享内存可能存在的问题。虽然它的传输速度快节约资源但是如果不加以约束一定会出现问题。 那么如何在共享内存中加入约束让两个进程间互不干扰呢这就是我们下一节要研究的问题信号量。
结束语
进程君父子找到了共享内存存在的局限性它们打算提供一个补救方案方案定制中。