Linux——(进程间通信)共享内存剖析

本文介绍Linux共享内存机制,包括原理、创建方法及进程间的共享内存读写操作。还讲解了如何通过系统调用实现共享内存的附加与分离。

1.共享内存原理

在Linux中,每个进程都有属于自己的进程控制块(PCB)和地址空间(Addr Space),并且都有一个与之对应的页表,负责将进程的虚拟地址与物理地址进行映射,通过内存管理单元(MMU)进行管理。两个不同的虚拟地址通过页表映射到物理空间的同一区域,它们所指向的这块区域即共享内存。

在这里插入图片描述

2.共享内存的创建

int shmget(key_t key, size_t size, int shmflg);
  1. key:共享标识符,标识系统的唯一IPC资源。
  2. size:需要申请共享内存的大小。在操作系统中,申请内存的最小单位为页,一页是4k字节,为了避免内存碎片,我们一般申请的内存大小为页的整数倍。
  3. shmflg:如果要创建新的共享内存,需要使用IPC_CREAT,IPC_EXCL,如果是已经存在的,可以使用IPC_CREAT或直接传0。
  4. 返回值:成功时返回一个新建或已经存在的的共享内存的操作句柄,失败返回-1并设置错误码。
  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/shm.h>
  4 #define key 0x89898989
  5 int main()
  6 {
  7 
  8     int shmid=shmget(key,1024,IPC_CREAT);
  9     if(shmid<0)
 10     {
 11         perror("shmget");
 12         return -1;
 13     }
 14     //
 15     return 0;
 16 
 17 }

查看共享内存信息:

ipcs -m

在这里插入图片描述

3.共享内存附加到进程(通过共享内存的读写操作)

void *shmat(int shmid, const void *shmaddr, int shmflg);
  1. shmid:共享内存操作句柄。
  2. shmaddr:附加共享内存的虚拟地址,当传递NULL值时,系统将自动分配一段未被使用的共享区的地址。
  3. shmflg:SHM_RDONLY位,则以只读方式连接此段,否则以读写方式连接此段。
  4. 返回值:成功返回共享内存附加到共享区的地址,并且内核将使其与该共享存储段相关的shmid_ds结构中的shm_nattch计数器加1(类似于引用计数);出错返回-1。

将共享内存附加到test.c文件,作为输入文件,通过指针lp将“linux”传入共享内存中去

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/shm.h>
  4 #include <string.h>
  5 
  6 #define key 0x88888888
  7 
  8 int main()
  9 {
 10 
 11     int shmid=shmget(key,1024,IPC_CREAT|0644);
 12     if(shmid<0)
 13     {
 14         perror("shmget");
 15         return -1;
 16     }
 17     //
 18     void* lp=shmat(shmid,NULL,0);
 19     printf("%p\n",(char *)lp);
 20     strcpy((char*)lp, "linux");
 21     return 0;
 22 
 23 }

将共享内存附加到read.c,作为读端,将“linux”从共享内存中读出

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<sys/shm.h>
  4 #include <string.h>
  5 #define key 0x88888888
  6 int main()
  7 {
  8 
  9     int shmid=shmget(key,1024,IPC_CREAT|0644);
 10     if(shmid<0)
 11     {
 12         perror("shmget");
 13         return -1;
 14     }
 15     //
 16     void* lp=shmat(shmid,NULL,0);
 17     printf("%p\n",(char *)lp);
 18     printf("%s\n",lp);
 19 
 20     return 0;
 21 
 22 }

运行结果:
在这里插入图片描述
**注意:**与管道不同的是,共享内存是访问,之中的值并不会被拷走!!!

3.共享内存和进程分离

int shmdt(const void *shmaddr) ;
  • shmaddr:chmat的返回值

分离之前附加了两个进程:在这里插入图片描述
将read.c加上分离语句:

shmdt(lp);

分离之后只剩一个进程:
在这里插入图片描述

3.共享内存的操作

int shmct1(int shmid,int cmd,struct shmid_ds *buf);
  • shmid :共享操作句柄
  • cmd : 告诉shmctl函数需要做什么操作
    • IPC_STAT :获取当前共享内存的属性信息,放在buf当中,buf是出参
    • IPC_SET :设置共享内存的属性信息,是用buf来进行设置的buf是入参
    • IPC_RMID:删除共享内存,buf可以直接传递为NULLbuf :共享内存的结构体
  • buf:共享内存结构体:在这里插入图片描述

注意: 删除共享内存,当使用shmctl或者使用ipcrm,删除共享内存之后,共享内存就实际被释放掉了,当共享内存被释放掉之后,共享内存的标识符会被设置成为0x00000000,表示其他进程不能通过之前的标识符找到该共享内存,并且共享内存的状态会被设置成为dest(destroy),但是还是有进程在附加着共享内存,当前描述共享内存的结构体并没有被释放,直到当前共享内存的附加进程数量为0的时候才会被释放掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值