您的位置

进程间通信之共享内存(一) 更新于2009-11-16 22:17:08 文章出处:来源:华清远见嵌入式学院

作者:曾宏安,华清远见嵌入式学院讲师。

1.共享内存概述

共享内存允许两个或更多进程共享一给定的存储区。因为数据不需要在各个进程之间复制,所以这是最快的一种进程间通信方式。使用共享内存时的关键点在于如何在多个进程之间对一给定的存储区进行同步访问。

例如若一个进程正在将数据放入共享内存区,则在它做完这一操作之前,其他进程不应该去取这些数据。通常,信号量被用来实现对共享内存访问的同步。

2.函数说明

共享内存的实现分为4个步骤。

第一步是创建共享内存,这里用到的函数是shmget,也就是从内存中获得一段共享内存区域。
        第二步是映射共享内存,也就是把这段创建的共享内存映射到具体的进程空间去。这里使用的函数是shmat。
        第三步是撤销映射的操作,其函数为shmdt。
        第四步是删除创建的共享内存,用到的函数是shmctl。

3.函数格式

以上函数用到的头文件如下所示。

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

shmget函数的语法

函数原型

int shmget( key_t key, /* IPC_PRIVATE */
        int size, /* 共享内存区大小 */
        int shmflg) /* 同open函数的权限位,也可以用8进制表示法 */

函数返回值

成功:共享内存段标识符
        出错:-1

shmat函数的语法

函数原型

char *shmat( int shmid, /* 要映射的共享内存区标识符 */
        const void *shmaddr, /* 将共享内存映射到指定位置(若为0则表示把该段共享内存映射到调用进程的地址空间)*/
        int shmflg) /* SHM_RDONLY :共享内存只读
        默认0 :共享内存可读写*/

函数返回值

成功:被映射的段地址
        出错:-1

shmdt函数的语法

函数原型

int shmdt(const void *shmaddr) /* 被映射的共享内存段地址 */

函数返回值

成功:0
        出错:-1

shmctl函数的语法

函数原型

int shmctl(int shmid, /* 要操作的共享内存区标识符 */
        int cmd, /*IPC _RMID : 删除共享内存
        IPC_STAT : 获取共享内存属性
        IPC_SET : 设置共享内存属性 */
        struct shmid_ds *buf) /* 指向保存共享内存属性的结构体的指针*/

函数返回值

成功:0
        出错:-1

4.使用实例

首先使用shmget函数,首先创建一个共享内存区,之后将其映射到本进程中,最后再解除这种映射关系并删除创建的共享内存。

这里要介绍的一个命令是ipcs,这是用于报告进程间通信机制状态的命令,它可以查看共享内存、消息队列等各种进程间通信机制的情况,这里使用了system函数用于调用命令ipcs,参考代码如下所示:

/*创建共享内存*/
        int shmid;
        void *shmadd;
        if ((shmid = shmget(IPC_PRIVATE,BUFSZ,0666)) < 0 )
    {
        perror(“fail to shmget ”);
        exit(-1);
    }
        syetem(“ipcs –m”);
        
/*映射共享内存*/
        if ((shmadd = shmat(shmid,0,0)) == NULL )
    {
        perror(“fail to shmat ”);
        exit(-1);
    }
        syetem(“ipcs –m”);
        /*删除共享内存*/
        if (shmdt(shmadd) < 0 )
    {
        perror(“fail to shmdt ”);
        exit(-1);
    }
        syetem(“ipcs –m”);
        if (shmctl(shmid, IPC_RMID, NULL) < 0 )
    {
        perror(“fail to shmctl ”);
        exit(-1);
    }
        syetem(“ipcs –m”);