Linux系统编程之进程间通信___3.共享内存

一.基本概念

引入:
无名管道、有名管道、信号通信都是通过在内核空间的对象进行通信。
IPC通信所涉及到的函数:
在这里插入图片描述

二.共享内存

1.共享内存的创建
  • 函数原型 int shmget(key_t key,int size,int shmflg)
    函数参数
    key:IPC_PRIVATE或ftok的返回值
    size:共享内存区大小
    shmg:同open函数的权限位,也可以用8进制表示法
    函数返回 成功:共享内存段标识符一D-文件描述符; 出错:-1
    eg1:
#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
  int shmid;
  shmid=shmget(IPC_PRIVATE,128,0777);
  if(shmid <0)
    {
    printf("creat share memory failure\n");
    return -1;
    }
   printf("creat share memory sucess shmid=%d\n",shmid);
   system("ipcs -m");//查看ipc对象
   sytem("ipcrm -m");//删除ipc对象 

  return 0;
}

备注:
查看内核中IPC对象的命令: ipcs -m
删除IPC :ipcrm -m id
system()函数返回值:成功,则返回进程的状态值;当sh不能执行时,返回127;失败返回-1;


(1) key:IPC_PRIVATE或ftok的返回值,两种方式所获得的key的区别

通过ftok的返回值创建的key:
ftok:创建key值。
char ftok(const char *path,char key)
参数:第一个参数:文件路径和文件名;
第二个参数:一个字符。
返回值:正确返回一个k值,出错返回-1

eg2:

#include "sys/types.h"
#include "sys/shm.h"
#include "signal.h"
#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
int main()
{
  int shmid;
  int key;
  //char *p;
  key=ftok("./a.c",'a');
  if(key <0)
    {
      printf("creat key fialure\n");
      return -2;
    }

  printf("creat key success key=%x\n",key);
  shmid=shmget (key,128,IPC_CREAT | 0777);//shmet在内核空间创建一个共享内存
  if(shmid <0)
    {
      printf("creat share memory failure\n");
      return -1;
    }
  printf("creat share memory sucess shmid=%d\n",shmid);
  
  system("ipcs -m");
 /*
  p= (char*) shmat(shmid,NULL,0);//可以将共享内存映射到用户空间去
  if(p=NULL)
  {
    printf("shmat function failure\n");
    return -3;
  }
// write share memory
 fgets(p,128,stdin);
// read share memory
 printf("share memory data:'s",p);
// printf("sencond read share memory data:'s",p);//这句话还能读出来
**去享内存特点:**
共享内存创建之后,一直存在于内核中,直到被删除或系统关闭:
共享内存和管道不一样,读取后,内容仍在其共享内存中。
  */
  return 0;
}

对比结果:IPC_PRIVATE操作时,共享内存的key值都一样,都是0。使用ftok来创建key值,对于不同的ftok函数的参数,key值不相同。只要key值是一样的,用户空间的进程通过这个函数打开,则会对内核的同一个IPC对象操作。具体区别:类似无名管道和有名管道的区别

(2)共享内存的映射:shmat将共享内存映射到用户空间中

能不能用read,write呢?read write必须每次都要进入内核
为了方便用户空间对共享内存的操作,使用地址映射的方式。

shmat函数功能:可以将共享内存映射到用户空间去,好处:可以在用户空间对内核的共享内存进行操作。
void *shmat (int shmid,const void *shmaddr,int shmflg);
参数:第一个参数:需要映射的共享内存的ID号;
第二个参数:映射到的地址,NULL为系统自动完成的映射;
第三个参数shmflg:
SHM_RDONLY共享内存只读; 默认是0,表示共享内存可读写。
返回值:成功:映射后的地址
失败:NULL

**共享内存特点:**

共享内存创建之后,一直存在于内核中,直到被删除或系统关闭;
共享内存和管道不一样,读取后,内容仍在其共享内存中。

2.共享内存的删除
(1)shmdt:将进程里的地址映射删除(删除用户空间的映射内存)

int shmdt(const void *shmaddr)
参数:shmaddr共享内存映射后的地址
返回值:成功:0
出错:1

在上述eg2加上:

shmdt (p);//删除在用户空间的内存
memcpy(p,"abcd"4//执行出现断错误 ,删除之后不可以再进行操作
(2)shmctl : 删除内核空间的共享内存对象。

函数原型:int shmctl(int shmid,int cmd,struct shmi_ds*buf)
函数参数:shmid:要操作的共享内存标识符。
cmd:
IPC_STAT(获取对象属性)实现了命令ipcs -m
IPC_SET(设置对象属性)
IPC_RMID(删除对象) 实现了命令ipcrm -m
buf: 指定IPC_STAT/PC SET时用以保存/设置属性。
函数返回值:成功:0; 出错:-1
在上述eg2加上:

shmctl(shmid,IPC_RMID,NULL);//删除内核空间的共享内存
system("ipcs -m");//查看对象 已经被删除查看不到
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值