个人主页:Rhzkp-CSDN博客
Linux专栏:戎小半的Linux_Rhzkp的博客-CSDN博客
进程间通信标准:
共享内存是一种进程间通信的机制,即不同进程的虚拟内存空间(虚拟内存地址不需要相同),映射到相同的物理内存中。如果某个进程向共享内存写入数据,所做的改动将【立即影响到】【同时访问】(加了锁的就不算“同时可以访问")同一段共享内存的任何其他进程
在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存
我们把将物理内存中的某段空间映射到多个进程的虚拟地址空间中的这种通信方式,叫做“共享内存”
在操作系统内,有多个共享内存同时存在,所以操作系统要将它们都管理起来
在共享内存中,存在引用计数,当引用计数为0时,表示没有进程在使用这块共享内存,此时就会被操作系统释放掉
共享内存的接口,system V的特性
key:用来标识共享内存的唯一性
size:共享内存的大小
shmflg:共享内存创建的选项
怎么评估共享内存存在还是不存在?
怎么保证两个不同的进程,拿到的就是同一个内存?
ipcs -m
ipcrm -m +共享内存id
能不能使用key来代替id?
不能。为什么?
key是要给内核进行区分唯一性的。用户使用指令管理共享内存是在用户层的,而指令内部是对系统调用进行了封装的。也就是说,指令是运行在用户层的,而key是给OS用的,所以不能使用key来代替id
void Destroy()
{
if(_shmid == gdefaultid)return;
int n=shmctl(_shmid,IPC_RMID,nullptr);
if(n > 0)
{
printf("shmctl delete shm: %d success!\n",_shmid);
}
else
{
EXR_EXIT("shmctl\n");
}
}
使用共享内存需要先把共享内存映射到进程的地址空间当中。
怎么映射的?
操作系统提供了一个系统调用shmat。调用这个系统调用的进程会把自己的堆栈之间的映射区和队友的共享内存建立映射。
成功:返回共享内存起始的虚拟地址
失败:-1
shmat,将共享内存挂接到进程的地址空间中
共享区属于用户空间
共享内存没有保护机制
消息队列和共享内存都属于system V标准
创建消息队列:
铺垫:
共享内存:
让两个进程看到同一份资源来实现通信:
数据不一致的解决方案
保护机制保护的是谁?或者说约束的是谁?
什么是临界区?
其实就是访问共享内存的代码段,这部分就是临界区
为什么会数据不一致?
任何时刻,只允许一个执行流访问资源,叫做互斥
在申请锁的时候,必须是原子的
没当一个执行流进入临界区时,就会申请锁,这说明锁本身也是共享的
那么谁来保证锁的安全?
对共享资源进行保护实际上是对访问共享资源的代码进行保护
原子性是什么?
信号灯,本质是一个计数器,用来表明临界资源中,资源数量的多少