内存共享

说明

内存共享是进程通信最快的手段,不需要多次转存数据就可实现的数据交换。是大数据实时性高的数据通信的最佳选择。下面我就介绍下内存共享常用的函数,以及使用注意事项。

函数说明

1.获取共享内存唯一标识(创建或寻找目标内存块)

  • int shmget(key_t key, size_t size, int shmflg);
    示例 :
	shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);//获取共享内存标识
    if(shmid < 0) 
    {
        printf("shmget error\n");
        return -1;
    }

key_t key :
32位的正整数,为有效地为共享内存段命名,再由系统生成一个相应的共享内存标识符(shmget()函数的返回值),只有shmget()函数才直接使用信号量键。当key的值为IPC_PRIVATE时,系统每次都会申请一个新的唯一标识。

size_t size:
以字节为单位指定需要共享的内存容量

int shmflg
权限标志,它的作用与open函数的mode参数一样,如果要想在key标识的共享内存不存在时,创建它的话,可以与IPC_CREAT做或操作。共享内存的权限标志与文件的读写权限一样,举例来说,0644,它表示允许一个进程创建的共享内存被内存创建者所拥有的进程向共享内存读取和写入数据,同时其他用户创建的进程只能读取共享内存。

返回
成功: 共享内存的唯一标识,后面可以根据这个标识进行相关操作。
失败: -1

2.连接共享内存

  • void *shmat(int shm_id, const void *shm_addr, int shmflg);
    示例 :
    shmptr = shmat(shmid, 0, 0);//与虚拟内存建立连接,实现共享且获取共享内存块地址
    if(shmptr < 0) 
    {
        printf("shmat error!\n");
        return -2;
    }

int shm_id
是由shmget()函数返回的共享内存唯一标识。

const void *shm_addr
指定共享内存连接到当前进程中的地址位置,通常为空,表示让系统来选择共享内存的地址。

int shmflg
是一组标志位,通常为0。

返回
成功:内存块地址
失败: -1

3.删除共享内存

  • int shmctl(int shm_id, int command, struct shmid_ds *buf);

示例 :

    shmctl(shmid, IPC_RMID, NULL); //删除共享内存
    if(shmctl_return < 0)
    {
        printf("shmctl_IPC_RMID error!\n");
        return -3; 
    }  

int shm_id
shmget()函数返回的共享内存标识符。

int command
是要采取的操作,它可以取下面的三个值 :
IPC_STAT:把shmid_ds结构中的数据设置为共享内存的当前关联值,即用共享内存的当前关联值覆盖shmid_ds的值。
IPC_SET:如果进程有足够的权限,就把共享内存的当前关联值设置为shmid_ds结构中给出的值
IPC_RMID:删除共享内存段

struct shmid_ds *buf
是一个结构指针,它指向共享内存模式和访问权限的结构。
struct shmid_ds
{
uid_t shm_perm.uid;
uid_t shm_perm.gid;
mode_t shm_perm.mode;
};

代码示例

shm-key.c

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

#define BUFF_SIZE 4095 //系统会申请4KB的整数倍内存,单位:Byte
#define PRIVATE_KEY 65536 //自定义的32位的唯一标识号

int main()
{
    int shmid = 0;
    char *shmptr = NULL;
    int shmctl_return = 0;

    shmid = shmget(PRIVATE_KEY, BUFF_SIZE, IPC_CREAT);//获取共享内存标识
    if(shmid < 0) 
    {
        printf("shmget error\n");
        return -1;
    }

    shmptr = shmat(shmid, 0, 0);//与虚拟内存建立连接,实现共享且获取共享内存块地址
    if(shmptr < 0) 
    {
        printf("shmat error!\n");
        return -2;
    }

    while(1)
    {
        printf("input:");
        scanf("%s", shmptr);
    }   

    shmctl(shmid, IPC_RMID, NULL); //删除共享内存
    if(shmctl_return < 0)
    {
        printf("shmctl_IPC_RMID error!\n");
        return -3; 
    }   

    
    return 0;
}

shm-read.c

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

#define BUFF_SIZE 4095 //系统会申请4KB的整数倍内存,单位:Byte
#define PRIVATE_KEY 65536 //自定义的32位的唯一标识号

int main()
{
    int shmid = 0;
    char *shmptr = NULL;
    int shmctl_return = 0;

    shmid = shmget(PRIVATE_KEY, BUFF_SIZE, IPC_CREAT);//获取共享内存标识
    if(shmid < 0) 
    {
        printf("shmget error\n");
        return -1;
    }

    shmptr = shmat(shmid, 0, 0);//与虚拟内存建立连接,实现共享且获取共享内存块地址
    if(shmptr < 0) 
    {
        printf("shmat error!\n",;
        return -2;
    }

    while(1)
    {
        printf("string :%s\n", shmptr);
        sleep(3);
    }   
	
    shmctl(shmid, IPC_RMID, NULL); //删除共享内存
    if(shmctl_return < 0)
    {
        printf("shmctl_IPC_RMID error!\n");
        return -3; 
    }   

    
    return 0;
}

注意事项

1.超过共享内存的大小限制

在一个linux服务器上,共享内存的总体大小是有限制的,这个大小通过SHMMAX参数来定义(以字节为单位)。如果机器上创建的共享内存的总共大小超出了这个限制,在程序中使用标准错误perror可能会出现以下的信息:“如果机器上创建的共享内存的总共大小超出了这个限制。”在程序中使用标准错误perror可能会出:“unable to attach to shared memory”

查看 SHMMAX 的值:

#sudo cat /proc/sys/kernel/shmmax

设置 SHMMAX 的值为2G:

echo "2147483648" &gt; /proc/sys/kernel/shmmax 

shell共享内存管理

  • 查看共享内存 :ipcs -m
  • 释放共享内存 :ipcrm <shmid>

LinuxC 释放内存需要做的处理

很明显,在上面的程序中,是无法释放共享内存的。需要加入signal(SIGINT,SIG_IGN)。具体内容,请移步下一章《管制系统中的信号量》

2018年01月13日 00时47分34秒 Wind

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值