进程间通信_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: [email protected]
    > 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: [email protected]
    > 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;
}

时间: 2024-10-09 04:06:26

进程间通信_05共享内存_System V实现的相关文章

进程间通信(9) - 共享内存(System V)

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.介绍 共享内存也是一种IPC,它是目前最快的IPC,它的使用方式是将同一个内存区映射到共享它的不同进程的地址空间中,这样这些进程间的通信就不再需要通过内核,只需对该共享的内存区域进程操作就可以了. 共享内存与其他的进程间通信最大的优点是:数据的复制只有两次,一次是从输入文件到共享内存区,一次从共享内存区到输出文件.而其他的则是需要复制4次:服务器将输入文件读入自己的进

Linux环境进程间通信:共享内存

共享内存简介 共享内存允许两个或多个进程共享一给定的存储区.因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC.共享内存的方式有两种:mmap()系统调用和系统V共享内存. mmap()系统调用 mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存.普通文件被映射到进程地址空间后,进程可以向访问普通内存一样对文件进行访问,不必再调用read(),write()等操作. 注:实际上,mmap()系统调用并不是完全为了用于共享内存而设计的.它本身提供了不同于一般对普

进程间通信(8) - 共享内存(posix)

1.前言 本篇文章的所有例子,基于RHEL6.5平台(linux kernal: 2.6.32-431.el6.i686). 2.共享内存介绍 前面所讲述的Linux下面的各种进程间通信方式,例如:pipe(管道),FIFO(命名管道),message queue(消息队列),它们的共同点都是通过内核来进行通信(假设posix消息队列也是在内核中实现的,因为posix标准没有规定它的具体实现方式).向pipe,fifo,message queue写入数据时,需要把数据从用户空间(用户进程)复制到

Linux进程IPC浅析[进程间通信SystemV共享内存]

Linux进程IPC浅析[进程间通信SystemV共享内存] 共享内存概念,概述 共享内存的相关函数 共享内存概念,概述: 共享内存区域是被多个进程共享的一部分物理内存 多个进程都可把该共享内存映射到自己的虚拟内存空间,所有用户空间的进程若要操作共享内存,都要将其映射到自己的虚拟内存空间中,通过映射的虚拟内存空间地址去操作共享内存,从而达到进程间的数据通信 共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容 本身不提供同

Linux进程间通信—使用共享内存

Linux进程间通信-使用共享内存 转自: https://blog.csdn.net/ljianhui/article/details/10253345 下面将讲解进程间通信的另一种方式,使用共享内存. 一.什么是共享内存 顾名思义,共享内存就是允许两个不相关的进程访问同一个逻辑内存.共享内存是在两个正在运行的进程之间共享和传递数据的一种非常有效的方式.不同进程之间共享的内存通常安排为同一段物理内存.进程可以将同一段共享内存连接到它们自己的地址空间中,所有进程都可以访问共享内存中的地址,就好像

Linux进程间通信--mmap共享内存(一)

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据[1]:一次从输入

Linux进程间通信--shmget()共享内存(二)

共享内存区域是被多个进程共享的一部分物理内存.如果多个进程都把该内存区域映射到自己的虚拟地址空间,则这些进程就都可以直接访问该共享内存区域,从而可以通过该区域进行通信.共享内存是进程间共享数据的一种最快的方法,一个进程向共享内存区域写入了数据,共享这个内存区域的所有进程就可以立刻看到其中的内容.这块共享虚拟内存的页面,出现在每一个共享该页面的进程的页表中.但是它不需要在所有进程的虚拟内存中都有相同的虚拟地址. 图 共享内存映射图 象所有的 System V IPC对象一样,对于共享内存对象的获取

进程间通信(共享内存),五种通信方式简单总结

共享内存:它是system V版本中最高效的一种通信机制,可以使多个进程共享同一地址空间,若有一个进程修改该地址空间,则其它共享该地址空间的进程可以同时看到,但它不提供同步与互斥关系.一般结合信号量来达到进程间的同步于互斥. 创建共享内存:int shmget(key_t _key,size_t size,int shmflg);//size必须为4096的倍数,即页表大小的倍数. 挂接进程:void* shmat(int shmid,const void* shmaddr,int shmflg

深入理解进程间通信之共享内存

共享内存可以说是最有用的进程间通信方式,也是最快的IPC形式.是针对其他通信机制运行效率较低而设计的.两个不同进程A.B共享内存的意思是,同一块物理内存被映射到进程A.B各自的进程地址空间.进程A可以即时看到进程B对共享内存中数据的更新,反之亦然.由于多个进程共享同一块内存区域,必然需要某种同步机制,互斥锁和信号量都可以. 采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝.对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共