linux:15共享内存

1.共享内存

(1)关于进程间的用到的两个命令:

1.ipcs命令

  • ipcs -s 信号量
  • ipcs -m 共享内存
  • ipcs -q 消息队列

2.ipcrm命令

  • ipcrm -s id:删除信号量
  • ipcrm -m id:删除共享内存
  • ipcrm -q id:删除消息队列

(2)共享内存工作原理

在这里插入图片描述
箭头显示了每个进程的逻辑地址空间到可用物理内存的映射关系

3.共享内存的解释

示意图:
在这里插入图片描述
sem.h

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/sem.h>
#include<sys/shm.h>
union semun
{
int val;
};
void sem_init();
void sem_p(int index);
void sem_v(int index);
void sem_destroy();

sem.c

#include "sem.h"

#define SEM_NUM 2
static int semid = -1;

int sem_init()
{
   //创建
   semid = semget((key_t)1234,SEM_NUM,IPC_CREAT|IPC_EXCL|0600);
   //如果全新创建成功的信号量等于-1,则失败
   if( semid == -1)
   {
      perror("semget error");
      return -1;
   }
   else
   {
      //如果全新创建成功,初始化
      int a[SEM_NUM] = {1,0};
      union semun semval;
      
      int i = 0;
      for(;i<SEM_NUM;i++)
      {
         semval.val = a[i];
         if(semctl(semid,i,SETVAL,semval) == -1)
         {
             perror("semctl setval error");
             return -1;
         }
      }
   }
    return 0;
}
int sem_p(int index)
{
  //判断传进来的值
  if(index < 0|| index >= SEM_NUM)
  {
    printf("sem_p:index arg error\n");
    return -1;
  }
  //合法,定义结构体
  struct sembuf buf;
  buf.sem_num = index;
  buf.sem_op = -1;//p
  buf.sem_flg = SEM_NUDO;

  if(semop(semid,&buf,1) == -1)
  {
     perror("semop p error");
     return -1;
  }
  
}
int sem_v(int index)
{
if(index < 0|| index >= SEM_NUM)
  {
    printf("sem_v:index arg error\n");
    return -1;
  }
  //合法,定义结构体
  struct sembuf buf;
  buf.sem_num = index;
  buf.sem_op = 1;//p
  buf.sem_flg = SEM_NUDO;

  if(semop(semid,&buf,1) == -1)
  {
     perror("semop v error");
     return -1;
  }
}
void sem_destroy();
{
  if (semctl(semid ,0 ,IPC_RMID) == -1)
  {
      perror("semctl rm error");
  }
}

4.所用到的函数

1.创建共享内存shmget函数

shmget(得到一个共享内存标识符或创建一个共享内存对象)

  • 所需头文件:
    #include <sys/ipc.h>
    #include <sys/shm.h>
  • 函数原型
    int shmget(key_t key, size_t size, int shmflg)
  • 函数传入值
    在这里插入图片描述
  • 函数返回值
    成功:返回共享内存的标识符
    出错:-1,错误原因存于error中
  • 附加说明
    上述shmflg参数为模式标志参数,使用时需要与IPC对象存取权限(如0600)进行|运算来确定信号量集的存取权限
    错误代码
    EINVAL:参数size小于SHMMIN或大于SHMMAX
    EEXIST:预建立key所指的共享内存,但已经存在
    EIDRM:参数key所指的共享内存已经删除
    ENOSPC:超过了系统允许建立的共享内存的最大值(SHMALL)
    ENOENT:参数key所指的共享内存不存在,而参数shmflg未设IPC_CREAT位
    EACCES:没有权限
    ENOMEM:核心内存不足
    在Linux环境中,对开始申请的共享内存空间进行了初始化,初始值为0x00。

注:如果用shmget创建了一个新的消息队列对象时,则shmid_ds结构成员变量的值设置如下:

    shm_lpid、shm_nattach、shm_atime、shm_dtime设置为0。

    msg_ctime设置为当前时间。

    shm_segsz设成创建共享内存的大小。

    shmflg的读写权限放在shm_perm.mode中。

    shm_perm结构的uid和cuid成员被设置成当前进程的有效用户ID,gid和cuid成员被设置成当前进程的有效组ID。
  • shmat函数原型(把共享内存区对象映射到调用进程的地址空间)

  • 头文件
    #include <sys/types.h>
    #include <sys/shm.h>

  • 函数原型
    void *shmat(int shmid, const void *shmaddr, int shmflg)

  • 函数传入值
    在这里插入图片描述

  • 函数返回值
    成功:附加好的共享内存地址
    出错:-1,错误原因存于error中

  • 附加说明
    fork后子进程继承已连接的共享内存地址。exec后该子进程与已连接的共享内存地址自动脱离(detach)。进程结束后,已连接的共享内存地址会自动脱离(detach)
    错误代码
    EACCES:无权限以指定方式连接共享内存
    EINVAL:无效的参数shmid或shmaddr
    ENOMEM:核心内存不足

3.shmdt函数(断开共享内存连接,与shmat函数相反,是用来断开与共享内存附加点的地址,禁止本进程访问此片共享内存)

  • 头文件
    #include <sys/types.h>
    #include <sys/shm.h>

  • 函数原型
    int shmdt(const void *shmaddr)

  • 函数传入值
    在这里插入图片描述

  • 附加说明
    本函数调用并不删除所指定的共享内存区,而只是将先前用shmat函数连接(attach)好的共享内存脱离(detach)目前的进程
    错误代码
    EINVAL:无效的参数shmaddr

4 shmctl函数原型(共享内存管理)

  • 头文件
    #include <sys/types.h>
    #include <sys/shm.h>

  • 函数原型
    int shmctl(int shmid, int cmd, struct shmid_ds *buf)

  • 函数传入值
    在这里插入图片描述

  • 函数返回值
    成功:0
    出错:-1,错误原因存于error中

  • 错误代码
    EACCESS:参数cmd为IPC_STAT,确无权限读取该共享内存
    EFAULT:参数buf指向无效的内存地址
    EIDRM:标识符为msqid的共享内存已被删除
    EINVAL:无效的参数cmd或shmid
    EPERM:参数cmd为IPC_SET或IPC_RMID,却无足够的权限执行

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值