进程间的通信 --- 共享内存

目录

 

共享内存:用于进程的数据共享,是最快的进程间通信方式

接口介绍:

实例:两个进程同时访问一块共享内存

共享内存特性:


共享内存:用于进程的数据共享,是最快的进程间通信方式

本质原理:共享内存本质来说就是一块物理内存,多个进程通将同一块物理内存都映射到自己的虚拟地址空间上,通过自己的虚拟地址空间进行访问,数据共享。

共享内存创建以后,在内核中是由标识符的,其他进程可以用过同一个标识符打开相同的共享内存,进行映射

 

 

 

为什么共享内存是最快的进程间通信方式:共享内存直接通过虚拟空间访问共享内存的数据,不像管道以及其他方式那样需要先将数据拷贝到内核态,获取数据时需要将数据从内核态中拷贝出,少了两次数据的拷贝,因此时最快的进程间的通方式。

共享内存的操作流程:

1.创建共享内存(开辟一块物理内存,并在内核中进行描述)

2.进程将共享内存映射到自己的虚拟地址空间上,并且获取映射后的首地址

3.对内存进行操作

4.不使用共享内存,则解除映射(不会删除共享内存,只是解除了共享内存与当前进程间的关系)

5.删除共享内存(共享内存有映射计数,只有为0时才会真的删除,否则不会被删除)

 

接口介绍:

 

创建共享内存

int shmget(key_t key,int size,int shmflag)------开辟一块物理内存,并在内核中进行描述

key: 共享内存的标识符,是一个整数,可以自己设置,可以以通过系统提供的接口设置

size:共享内存的大小

shmflag:共享内存的标志位 IPC_CREAT--若共享内存不存在则创建,存在则打开。IPC_EXCL与IPC_CREAT同时使用,若共享内存不存在则创建,存在则报错。

mode:共享内存的访问权限 0664

返回值:返回的共享内存在代码中的操作句柄,是一个数字,通过这个数字可以在内核中找到共享内存的描述

//创建共享内存   
int shmid = shmget(IPC_KEY,32,IPC_CREAT | 0664); 
 if(shmid < 0)   
 {   
  perror("shmger error");  
  return -1;  
 }


 

映射到虚拟地址空间

void* shmat(int shmid, void *addr, int shmflag)

shmid: shmget接口返回的操作句柄

addr: 映射到虚拟地址空间的首地址,推荐NULL,由操作系统进行映射地址选择

shmflag: SHM_RDNOLY-只读/ 0 可读可写(前提时对共享内存具有相对的操作权限)

返回值:映射到虚拟地址空间的首地址,通过这个首地址可以访问这块共享内存

 //映射
   void * shm_start = shmat(shmid,NULL,0); // 0 可读可写
   if(shm_start == (void*)-1)
   {
     perror("shmat error");
   }

解除映射

int shmdt(void*shm_start);

shm_start:映射首地址,传入进来进行解除映射关系

//解除映射关系
  shmdt(shm_start)

删除共享内存

int shmctl(int shmid,int cmd,struct shmid_ds *buf)

shmid: 共享内存的操作句柄

cmd: 具体要进行的操作 IPC_RMID --- 删除共享内存

buf: 同于设置/获取共享内存信息,用不到置NULL

 //删除共享内存
shmctl(shmid,IPC_RMID,NULL);

 

ipcs 查看进程间通信资源

 

实例:两个进程同时访问一块共享内存

 

进程1 shm_read.c  从共享内存中读取数据

 #include <stdio.h>
 #include <unistd.h>
 #include <sys/shm.h>
 #include <string.h>
 
 #define IPC_KEY 0x12345678
 
 int main()
 {
   //创建共享内存
   int shmid = shmget(IPC_KEY,32,IPC_CREAT | 0664);
   if(shmid < 0)
   {
   perror("shmger error");
   return -1;
   }
   //映射
   void * shm_start = shmat(shmid,NULL,0); // 0 可读可写
   if(shm_start == (void*)-1)
   {
     perror("shmat error");
   }
   //内存操作
   while(1)
   {
     printf("shm:[%s]\n",(char*)shm_start);
     sleep(1);                                                          
   }
   //解除映射关系
   shmdt(shm_start);
   //删除共享内存
   shmctl(shmid,IPC_RMID,NULL);

进程2:shm_write.c 向共享内存中写入数据 

#include <stdio.h>
#include <unistd.h>
#include <sys/shm.h>
#include <string.h>

#define IPC_KEY 0x12345678

int main()
{
  //创建共享内存
  int shmid = shmget(IPC_KEY,32,IPC_CREAT | 0664);
  if(shmid < 0)
  {
  perror("shmger error");
  return -1;
  }
  //映射
  void * shm_start = shmat(shmid,NULL,0); // 0 可读可写
  if(shm_start == (void*)-1)
  {
    perror("shmat error");
  }
  //内存操作
  int i = 0;
  while(1)
  {
    sprintf(shm_start,"woshinidie+%d",i++);                          
    sleep(1);
  }
  //解除映射关系
  shmdt(shm_start);
  //删除共享内存

 

 

共享内存特性:

共享内存生命周期随内核

共享内存时最快的进程间通信方式

注意:

共享内存不自带同步与互斥,它的操作需要程序员的额外保护

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值