linux---共享内存

共享内存

   共享内存区是最快的IPC形式,一旦这样的内存映射到共享它的进程的地址空间,这些进程间数据传递不再涉及到内核。

   前几种,内核提供资源,代码借助内核,从用户态切换到内核态,完成之后,又要从内核态切换到用户态。

共享内存是通过MMU机制,直接映射到内核。


共享内存的特点

  1. 双向通信,可用于随意的进程,不一定非要有亲缘关系
  2. 没有面向字节流或者数据报的概念,就是一块内存,可以随机访问
  3. 生命周期随内核,需要人为显式删除共享内存或者重启内核。
  4. 没有内置同步互斥机制

查看系统中存在的共享内存

ipcs -m

删除系统中存在的共享内存

ipcrm -m + shmid

和前面两种进程间通信类似,共享内存也有一个专门的结构来描述它。

    struct shmid_ds {
        struct ipc_perm     shm_perm;   /* operation perms */
        int         shm_segsz;  /* size of segment (bytes) */
        __kernel_time_t     shm_atime;  /* last attach time */
        __kernel_time_t     shm_dtime;  /* last detach time */
        __kernel_time_t     shm_ctime;  /* last change time */
        __kernel_ipc_pid_t  shm_cpid;   /* pid of creator */
        __kernel_ipc_pid_t  shm_lpid;   /* pid of last operator */
        unsigned short      shm_nattch; /* no. of current attaches */
        unsigned short      shm_unused; /* compatibility */
        void            *shm_unused2;   /* ditto - used by DIPC */
        void            *shm_unused3;   /* unused */
    };

先学习有关于共享内存的相关函数

shmget 函数

原型: int shmget(key_t key, size_t size, int shmflg);
功能: 用来创建或者访问共享内存
参数:
key : 唯一标识符
size : 创建的共享内存的大小,以 4k(页表的大小) 大小为单位进行分配空间。
shmflg : 标志位
返回值:
成功返回一个非负整数,该段的共享内存的标志码,失败则返回-1

shmat函数

原型: void *shmat(int shmid, const void *shmaddr, int shmflg);
功能: 将共享内存映射到进程地址空间
参数:
shmid : 要映射的共享内存的标识
shmaddr :指定连接的地址,一般都是填NULL,让操作系统自动映射
shmflg :标志位
返回值:
成功返回一个指针,指向共享内存的第一个字节,失败返回-1
/* mode for attach */
#define SHM_RDONLY 010000 /* read-only access */
#define SHM_RND 020000 /* round attach address to SHMLBA boundary */
#define SHM_REMAP 040000 /* take-over region on attach */
#define SHM_EXEC 0100000 /* execution access */

shmdt函数

原型 :int shmdt(const void *shmaddr);
功能 :将共享内存段与当前进程脱离,并不是删除这段共享内存,只是脱离映射关系
参数 :
shmaddr :指向attach后的地址空间
返回值 :
成功返回0, 失败返回 -1
shmctl函数
原型 :int shmctl(int shmid, int cmd, struct shmid_ds *buf);
功能 : 控制共享内存
参数 :
shmid :共享内存的标识码
cmd :要做什么操作 (IPC_STAT、IPC_SET、IPC_RMID)
buf :指向一个保存着共享内存的模式状态和访问权限的数据结构
返回值 :
成功返回0,失败返回-1
cmd :
IPC_STAT :把shmid_ds结构中的数据设置为共享内存的当前关联值
IPC_SET :在进程有足够权限前提下,把共享内存的当前关联值设置为shmid_ds数据结构中给出的值
IPC_RMID :删除共享数据段


common.h
用于封装为功能性更完整的函数

       #pragma once

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

       #define PATHNAME "."
       #define PROJ_ID 0x1

       int CreateShm(size_t size);  // 创建一个共享内存

       int GetShm();   //获取一个共享内存

       int DestroyShm(int shmid);  //销毁一个共享内存

common.c

       #include "common.h"

       //由于创建和获取的代码基本上一致,就只有shmget的参数有些不同。
       //所以就将其封装。将shmget的参数作为封装好的函数的参数
       int CommonShm(size_t size, int flags)
       {
           key_t key = ftok(PATHNAME, PROJ_ID); 
           if(key < 0)
           {
               perror("ftok");
               return -1;
           }

           int shmid = shmget(key, size, flags);
           if(shmid < 0)
           {
               perror("shmget");
               return -1;
           }
           return shmid;
       }
       //创建一个共享内存
       int CreateShm(size_t size)
       {
           return CommonShm(size, IPC_CREAT | IPC_EXCL | 0666);
       }
       //获取一个共享内存
       int GetShm()
       {
           return CommonShm(0,IPC_CREAT);
       }

       //销毁一段共享内存
       int DestroyShm(int shmid)
       {
           int ret = shmctl(shmid, IPC_RMID, NULL);
           if(ret < 0)
           {
               perror("shmctl");
               return -1;
           }
           return 0;
       }

server.c
服务器端代码

       #include "common.h"

       int main()
       {
           int shmid = CreateShm(1024);
           if(shmid < 0)
           {
               printf("CreateShm");
               return -1;
           }

           printf("shmid : %d\n",shmid);

           char *ptr = (char*)shmat(shmid, NULL, SHM_RDONLY);
           while(1)
           {
               printf("%s\n", ptr);
               sleep(1);
           }
           shmdt(ptr);
           return 0;
       }

client.c
客户端代码

       #include "common.h"

       int main()
       {
           int shmid = GetShm();
           if(shmid < 0)
           {
               printf("GetShm");
               return -1;
           }
           printf("shmid: %d\n",shmid);
           // 0 表示
           char *ptr = (char*)shmat(shmid, NULL, 0);
           int i = 1;
           while(1)
           {
               int j = 0;
               while(j < i)
               {
                   ptr[j] = 'A' + i - 1;
                   j++;
               }
               ptr[j] = '\0';
               i++;
               i %= 26;
               sleep(1);
           }
           shmdt(ptr);
           return 0;
        }
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值