首页 > 代码库 > 进程间通信_05共享内存_System V实现

进程间通信_05共享内存_System V实现

一 概念
内核分配的一块存储去,多个进程可以将物理内存映射到进程的虚拟地址空间,从而实现对内存的直接操作,是效率最高的IPC
消息队列和管道都有在用户地址空间和内核空间相互复制产生的开销。


二 操作函数
1 创建共享内存
#include <sys/ipc.h>
#include <sys/shm.h>
int shmget( key_t key,                      //代表共享内存唯一性的key值
                    size_t size,            //共享内存的大小
                    int shmflg);            //共享内存的属性设置   
//返回值:>0 (成功,返回共享内存的标识符)  -1(失败,错误信息见errno)
其中,shmflg决定共享内存的操作属性和权限。
如:0666|IPC_CREAT表示,执行创建共享内存的操作并设置共享内存的权限为666。


2 进程连接共享内存
#include <sys/types.h>
#include <sys/shm.h>
void *shmat(int shmid,                         //共享内存的标识符
                     const void *shmaddr,      //设置共享内存在进程中的地址,一般置为0由系统分配
                     int shmflg);              //共享内存的操作标志,一般置为0,表示进程有读写权限
//返回值:非(void*)-1(成功,返回映射的地址值)、(void*)-1(连接失败,失败信息见errno)


3 进程断开和共享内存的连接
#include <sys/types.h>
#include <sys/shm.h>
int shmdt(const void *shmaddr);  //连接的地址值
//返回值:0(断开成功)、-1(断开连接失败,失败信息见errno)


4 删除共享内存/设置共享内存属性
#include <sys/ipc.h> #include <sys/shm.h>
int shmctl(int shmid,                          //共享内存标识符
           int cmd,                            //操作命令
           struct shmid_ds *buf);              //命令对应的参数
其中,
cmd取值如下:IPC_STAT     获取共享内存的属性信息
                         IPC_SET       设置共享内存的属性信息
                         IPC_RMID    删除共享内存

buf参数的结构体如下:
struct shmid_ds {
    struct ipc_perm shm_perm;              /* Ownership and permissions */
    size_t shm_segsz;                       /* Size of segment (bytes) */
    time_t shm_atime;                     /* Last attach time */
    time_t shm_dtime;                     /* Last detach time */
    time_t shm_ctime;                      /* Last change time */
    pid_t shm_cpid;                          /* PID of creator */
    pid_t shm_lpid;                           /* PID of last shmat()/shmdt() */
    shmatt_t shm_nattch;                 /* No. of current attaches */
    ...
};
上面结构体中的struct ipc_perm结构如下:
struct ipc_perm {
    key_t key;                             /* Key supplied to shmget() */
    uid_t uid;                              /* Effective UID of owner */
    gid_t gid;                              /* Effective GID of owner */
    uid_t cuid;                             /* Effective UID of creator */
    gid_t cgid;                             /* Effective GID of creator */
    unsigned short mode;         /* Permissions + SHM_DEST and  SHM_LOCKED flags */ 
    unsigned short seq;             /* Sequence number */
};




三 使用实例

1 创建共享内存写数据
/*************************************************************************
    > File Name: testshmw.c
    > Author: qiaozp
    > Mail: qiaozongpeng@163.com
    > Created Time: 2014-9-22 10:58:30
    > Step: 1 创建共享内存 shmget
            2 连接共享内存 shmat
            3 操作共享内存 
            4 断开共享内存 shmdt
 ************************************************************************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;

#define BUFF_LEN 1024
typedef struct 
{
    bool isOkToRead;
    char data[BUFF_LEN];
}Sbuff;

int main()
{
    int shmid = 0;
    void* shm = NULL;
    //1 创建key值为1234的共享内存
    if((shmid = shmget((key_t)1234, (size_t)sizeof(Sbuff) , 0666 | IPC_CREAT)) == -1)
    {
        cout << "创建共享内存错误,错误信息:" << strerror(errno) << endl;
        return -1;
    }
    
    //2 连接共享内存
    if((shm = shmat(shmid, 0, 0)) == (void*)-1)
    {
        cout << "连接共享内存错误,错误信息:" << strerror(errno) << endl;
        return -1;
    }
    
    //3 直接对内存进行操作
    Sbuff* buff = (Sbuff*)shm;
    while(1)
    {
        if(buff->isOkToRead)
        {
            sleep(1);
            continue;
        }
        cout << "请输入写入共享内存的数据:";
        scanf("%s", buff->data);
        buff->isOkToRead = true;
        if(strncasecmp(buff->data, "end", 3) == 0)
        {
            cout << "收到end命令,断开和共享内存的连接" << endl;
            //4 断开共享内存
            shmdt(shm);
            break;
        }
    }
    
    return 0;
}   




2 创建工程内存读数据
/*************************************************************************
    > File Name: testshmr.c
    > Author: qiaozp
    > Mail: qiaozongpeng@163.com
    > Created Time: 2014-9-22 10:58:14
    > Step: 1 创建共享内存 shmget
            2 连接共享内存 shmat
            3 操作共享内存 
            4 断开共享内存 shmdt
 ************************************************************************/
#include <sys/ipc.h>
#include <sys/shm.h>
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
using namespace std;

#define BUFF_LEN 1024
typedef struct 
{
    bool isOkToRead;
    char data[BUFF_LEN];
}Sbuff;

int main()
{
    int shmid = 0;
    void* shm = NULL;
    //1 创建共享内存
    if((shmid = shmget((key_t)1234, (size_t)sizeof(Sbuff) , 0666 | IPC_CREAT)) == -1)
    {
        cout << "创建共享内存错误,错误信息:" << strerror(errno) << endl;
        return -1;
    }
    
    //2 连接共享内存
    if((shm = shmat(shmid, 0, 0)) == (void*)-1)
    {
        cout << "连接共享内存错误,错误信息:" << strerror(errno) << endl;
        return -1;
    }
    
    //3 操作共享内存
    Sbuff* buff = (Sbuff*)shm;
    buff->isOkToRead = false;
    while(1)
    {
        if(!buff->isOkToRead)
        {
            sleep(1);
            continue;
        }
        cout << "共享内存中现在的数据为:" << buff->data << endl;
        buff->isOkToRead = false;
        if(strncasecmp(buff->data, "end", 3) == 0)
        {
            cout << "收到end命令,断开和共享内存的连接" << endl;
            //4 断开共享内存
            shmdt(shm);
            break;
        }
    }
    
    //5 删除共享内存
    if(shmctl(shmid, IPC_RMID, 0) == -1)
    {
        cout << "删除共享内存失败,失败信息:" << strerror(errno) << endl;
        return -1;
    }
    
    return 0;
}   




进程间通信_05共享内存_System V实现