system V-IPC 之共享内存

一、共享内存的逻

上图所示,当进程 P1 向其虚拟内存中的区域 1 写入数据时,进程 2 就能同时在其虚 拟内空间的区域 2 看见这些数据,中间没有经过任何的转发,效率极高。

共享内存是最快的IPC形式。一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递将不再涉及到内核,换句话说,进程将不再通过执行进入系统内核的系统调用来传递彼此的数据。
 

二、使用共享内存的一般步骤是:

1,获取共享内存对象的 ID 

注意:

(1)需创建y一个唯一的key值--->ftok();

(2)id = shmget();开辟共享内存空间,空间只能是偶数

2,将共享内存映射至本进程虚拟内存空间的某个区域 

 (把共享内存的空间映射进程的虚拟内存空间----->*p = shmat();

   写入和读取都可以用拿到的指针p去直接修改。)

3,当不再使用时,解除映射关系

(取消映射----->shmdt(p);)

4,当没有进程再需要这块共享内存时,删除它。

(删除----->shmctl();)

三、相关API:

1.创建共享内存

获取共享内存的 ID

文件

#include <sys/ipc.h>

#include <sys/shm.h>

int shmget(key_t key, size_t size, int shmflg);

参数

key

共享内存的键

size

共享内存的尺寸 (PAGE_SIZE 的整数倍)

shmflg

IPC_CREAT

如果 key 对应的共享内存不存在,则创建之

IPC _EXCL

如果该 key 对应的共享内存已存在,则报错

SHM _HUGETLB

使用“大页面”来分配共享内存

SHM _NORESERVE

不在交换分区中为这块共享内存保留空间

mode

共享内存的访问限 (八进制,如 0644)

回值

成功

共享内存的 ID

- 1

 key 指定为为 IPC_PRIVATE,则会自动产生一个随机未用的新键值

2.映射或解除映射

对共享内存进行映射,或者解除映射

文件

#include <sys/types.h>

#include <sys/shm.h>

void *shmat(int shmid, const void *shmaddr, int shmflg);

int shmdt(const void *shmaddr);

参数

shmid

享内存 ID

shmaddr

shmat( )

1 ,如果为 NULL,则系统会自动选择一个合适的虚拟 内存间地址去映射共享内存。

2果不为 NULL,则系统会根据 shmaddr 来选择一 个合适的内存区域。

shmdt( )

共享内存的首地址

shmflg

SHM_RDONLY

以只读方式映射共享内存

SHM_REMAP

映射,此时 shmaddr 不能为 NULL

SHM_RND

自动选择 shmaddr 小的最大页对齐地址

回值

成功

共享内存的首地址

- 1

注意:共享内存只能以只读或者可读写方式映射,无法以只写方式映射

解除映射之后,进程不能再允许访问 SHM

3.删除映射

获取或者设置共享内存的相关属性

文件

#include <sys/ipc.h>

#include <sys/shm.h>

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

参数

shmid

享内存 ID

cmd

IPC_STAT

获取属性信息,放置到buf 

IPC_SET

属性信息为 buf 指向的内容

IPC _RMID

将共享内存标记为“即将被删除”状态

IPC _INFO

获得关于共享内存的系统限制值信息

SHM _INFO

获得系统为共享内存消耗的资源信息

SHM _STAT

 IPC_STAT,但 shmid 为该 SHM 在内核中记录所 SHM 信息的数组的下标,因此通过迭代所有的 下标可获得系统中所有 SHM 的相关信息

SHM _LOCK

系统将该 SHM 交换至 swap 分区

SHM _UNLOCK

允许统将该 SHM 交换至 swap 分区

buf

性信息结构体指针

回值

成功

IPC _INFO

内核记录所有 SHM 信息的数组的下标最大值

SHM _INFO

SHM _STAT

标值为 shmid SHM ID

- 1

代码演示:

 #include <sys/types.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
 #include<fcntl.h>
 #include<sys/shm.h>
 #include<errno.h>


 int main()
 {
   key_t key=ftok("./",1);
   if(key<0)
  {
    perror("ftok err");
    return -1;
  }
 //1.创建共享内存
 int id=shmget(key,1024,IPC_CREAT|IPC_EXCL|0644);
 if(id<0)
 {
   if(errno==EEXIST)
 {
   id = shmget(key,1024,0644);
 }
 else
 {
   perror("shmget err");
   return -1;
 }
 }
 //2.映射
 char *p=shmat(id,NULL,0);  //用shmat()映射到你的虚拟内存
 if(p ==(char *)-1)
 {
   perror("shmat err");
   return -1;
 }
 fgets(p,32,stdin);
 printf("%s\n",p);

 }

运行结果:在共享内存中输入hello world,将打印出hello world;

在虚拟机终端输入 ipcs -m;查看共享内存;

删除指定的共享内存:ipcrm -m SHM_ID 或者 ipcrm -M shm_key

 

取消映射和删除共享内存的代码

 //取消映射
 shmdt(p);
 //删除共享内存
 shmctl(id,IPC_RMID,NULL);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值