共享内存概述

       共享内存允许两个或者多个进程共享给定的存储区域

   共享内存的特点:

     共享内存是进程间共享数据的一种最快的方法

           一个进程向共享的内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容

     使用共享内存要注意的是多个进程之间对一个给定存储区访问的互斥

           若一个进程正在向共享内存区写数据, 则在它做完这一步操作前, 别的进程不应当去读、写这些数据

  共享内存示意图

  获得一个共享存储标识符 

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

/*
 *功能:
 *  创建或打开一块共享内存区
 *参数:
 *  key: IPC键值
 *  size: 该共享存储段的长度(字节)
 *  shmfig: 标识函数的行为及共享内存的权限
 *    IPC_CREAT: 如果不存在就创建
 *    IPC_EXCL: 如果已经存在则返回失败
 *    位或权限位: 共享内存位或权限位后可以设置共享内存的访问权限
 *return:
 *  成功:共享内存标识符
 *  失败:-1
 */
int shmget(key_t key, size_t size, int shmfig)

共享内存映射(attach)

#include <sys/types.h>
#include <sys/shm.h>

/*
 *功能:
 *  将一个共享内存段映射到调用进程的数据段中
 *参数:
 *  shmid: 共享内存标识符
 *  shmaddr: 共享内存映射地址(若为 NULL 则由系统自动指定)
 *  shmfig: 共享内存段的访问权限和映射条件
 *    0: 共享内存具有可读可写权限
 *    SHM_RDONLY: 只读
 *    SHM_RND:  shmaddr 非空时才有效
 *      没有指定 SHM_RND,此段连接到 shmaddr 所指定的地址上(shmaddr 必需页对齐)
 *      指定 SHM_RND,此段连接到 shmaddr- shmaddr%SHMLBA 所表示的地址上
 *return:
 *  成功:共享内存段映射地址
 *  失败:-1
 *注意:
 *  shmat 函数使用的时候第二个和第三个参数一般设为 NULL 和 0,即系统自动指定共享内存地址,并且共享内存可读可写
 */
void *shmat(int shmid, const void *shmaddr, int shmfig)

解除共享内存映射(detach)

#include <sys/types.h>
#include <sys/shm.h>

/*
 *功能:
 *  将共享内存和当前进程分离(仅仅是断开联系并不删除共享内存)
 *参数:
 *  shmaddr:共享内存映射地址
 *return:
 *  成功:0
 *  失败:-1
 */
int shmdt(const void *shmaddr)

共享内存控制

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

/*
 *功能:
 *  共享内存空间的控制
 *参数:
 *  shmid:共享内存标识符
 *  cmd: 函数功能的控制
 *    IPC_RMID: 删除
 *    IPC_SET: 设置 shmid_ds 参数
 *    IPC_STAT: 保存 shmid_ds 参数
 *    SHM_LOCK: 锁定共享内存段(超级用户)
 *    SHM_UNLOCK:  解锁共享内存段
 *  buf: shmid_ds 数据类型的地址,用来存放或修改共享内存的属性
 *return:
 *  成功: 0
 *  失败:-1
 */
int shmctl(int shmid, int cmd, struct shmid_ds *buf)

写:

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

#defind    BUFSZ    2048

int main(int argc, char *argv[])
{
    int shmid;
    int ret;
    key_t key;
    char *shmadd;

    key = ftok(".", 2012);
    if(key == -1)
    {
        perror("ftok");
    }

    system("ipcs -m");
    // 打开共享内存
    shmid = shmget(key, BUFSZ, IPC_CREAT | 0666);
    if(shmid < 0)
    {
        perror("shmget");
        exit(-1);
    }
    
    //映射
    shmadd = shmat(shmid, NULL, 0);
    if(shmadd < 0)
    {
        perror("shmat");
        exit(-1);
    }
    //读共享内存区数据    
    printf("data = [%s]\n",shmadd);

    //分离共享内存和当前进程
    ret = shmdt(shmadd);
    if(ret < 0)
    {
        perror("shmdt");
        exit(1);
    }
    else
    {
        printf("daleted shared-memory\n");
    }
    //删除共享内存
    shmctl(shmid, IPC_RMID,NULL);
    system("ipcs -m");
    
    return 0;
}

读 

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

#define BUFSZ 2048

int main(int argc, char *argv[])
{
	int shmid;
	int ret;
	key_t key;
	char *shmadd;
	
	key = ftok(".", 2012);
	if(key == -1)
	{
		perror("ftok");
	}
	//创建共享内存
	shmid = shmget(key, BUFSZ, IPC_CREAT | 0666);
	if(shmid < 0)
	{
		perror("shmget");
		exit(-1);
	}
	//映射
	shmadd = shmat(shmid, NULL, 0);
	if(shmadd < 0)
	{
		perror("shmat");
		_exit(-1);
	}
	//拷贝数据到共享内存
	printf("copy data to shared -memorty\n");
	bzero(shmadd, BUFSZ);
	strcpy(shmadd, "data in shared memory\n");
	
	return 0;
}