共享内存
进程间通信的本质是让不同的进程访问一块公共的资源。
1、共享内存是进程间通信最快的方式(为什么)
2、共享内存不提供任何的同步与互斥关系。(由用户维护,可以用信号量)
以下图解释了问题1,原因是,由于共享内存的机制,两个进程不需要拷贝拷贝数据,这个特点可能在数据较少的情况下看不出来,但是数据较多时,优势较为明显。
下图是shmat之前之后的共享内存示意图:(shmget获得共享内存后需要挂接)
|  | 
函数:
用于Linux进程通信共享内存。共享内存函数由shmget、shmat、shmdt、shmctl四个函数组成。
shmat(把共享内存区对象映射到调用进程的地址空间)
void *shmat(int shmid, const void *shmaddr, int shmflg)
参数:
| shmid | 共享内存标识符 | 
| shmaddr | 指定共享内存出现在进程内存地址的什么位置,直接指定为NULL让内核自己决定一个合适的地址位置 | 
| shmflg | 如果设置为SHM_RDONLY是只读模式,其他为读写模式 | 
返回值:成功返回附加好的共享内存地址
shmdt(断开共享内存连接)
int shmdt(const void *shmaddr)
参数:
shmaddr:连接的共享内存的起始地址
返回值:成功返回0
shmget(得到一个共享内存标识符或创建一个共享内存对象)
int shmget(key_t key, size_t size, int shmflg)
参数:
| key | 大于0的32位整数:视参数shmflg来确定操作。通常要求此值来源于ftok返回的IPC键值 | 
| size | 大于0的整数:新建的共享内存大小,以字节为单位 | 
| flags | 有IPC_CREAT和IPC_EXCL(用法同前面写的一致) | 
返回值:成功返回共享内存标示符
注:system V分配内存的方法以页为基本单位,一般以页的整数倍分配。
shmctl完成对共享内存的控制
int shmctl(int shmid, int cmd, struct shmid_ds *buf)
参数:
| shmid | 共享内存标识符 | |
| cmd | IPC_STAT:得到共享内存的状态,把共享内存的shmid_ds结构复制到buf中 | |
| IPC_SET:改变共享内存的状态,把buf所指的shmid_ds结构中的uid、gid、mode复制到共享内存的shmid_ds结构内 | ||
| IPC_RMID:删除这片共享内存 | ||
| buf | 共享内存管理结构体。具体说明参见共享内存内核结构定义部分 | 
共享内存实现通信的例子
comm.h
#pragma once #include<errno.h> #include<sys/ipc.h> #include<sys/shm.h> #include<string.h> #define _PATH_NAME_ "/temp" #define _PROJ_ID_ 0x6666 int create_shm(int size); int get_shm(); int destory_shm(int shm_id); void* shm_at(int shm_id); int shm_dt(void*shmaddr);
comm.c
#include"comm.h"
static int comm_create_shm(int size,int flags)
{
    key_t _key = ftok(_PATH_NAME_,_PROJ_ID_);
    if(_key<0)
    {
        perror("ftok");
        return -1;
    }
//    int shm_id=shmget(_key,size,IPC_CREAT | IPC_EXCL);
    int shm_id=shmget(_key,size,flags);
    if(shm_id < 0)
    {
        perror("shmget");
        return -2;
    }
    return shm_id;
}
int create_shm(int size)
{
    int flags = IPC_CREAT | IPC_EXCL|0666;
    return  comm_create_shm(size,flags);
}
int get_shm()
{
    
    int flags = IPC_CREAT;
    return  comm_create_shm(0,flags);
}
int destory_shm(int shm_id)
{
    if(shmctl(shm_id,IPC_RMID,NULL)<0)
    {    
        perror("shmctl");
        return -1;
    }
    return 0;
}
void* shm_at(int shm_id)
{
    return shmat(shm_id,NULL,0);
}
int shm_dt(void* shmaddr)
{
    return shmdt(shmaddr);
}server.c
#include"comm.c"
int main()
{
    int shm_id = create_shm(4096);
    sleep(5);
    char* buf = (char*)shm_at(shm_id);
    sleep(1);
    sleep(1);
    while(1)
    {
        printf("%s\n",buf);
        sleep(1);
        if(strcmp(buf,"AAAAA") == 0)
        {
            break;
        }
    }
    shm_dt(buf);
    sleep(5);
    destory_sem(sem_id);
    return 0;
}client.c
#include"comm.c"
int main()
{
    int shm_id = get_shm();
    char* buf = (char*)shm_at(shm_id);
    int index = 0;
    while(1)
    {
        buf[index++]=‘A‘;
        buf[index]=‘\0‘;
        sleep(1);
        if(index>5)
        {
            break;
        }
    }
    sleep(5);
    shm_dt(buf);
    sleep(5);
    return 0;
}原文:http://10798301.blog.51cto.com/10788301/1836291