Linux进程间通信(IPC)编程实践(七)共享内存的使用-System V共享内存(API)

注册 Vultr VPS 送你10美金 免费玩4个月

上一篇博文提到的系统调用mmap通过映射一个普通文件实现共享内存。那么本文中介绍的System V 共享内存则是通过映射特殊文件系统shm中的文件实现进程间的共享内存通信。也就是说,每个共享内存区域对应特殊文件系统shm中的一个文件。执行过程是先调用shmget,再调用shmat。对于每个共享的内存区,内核维护如下的信息结构,定义在<sys/shm.h>头文件中。

//System V 共享内存基本数据结构  
struct shmid_ds  
{  
    struct ipc_perm shm_perm;    /* Ownership and permissions: System V IPC所共有的数据结构 */  
    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(2)/shmdt(2) */  
    shmatt_t        shm_nattch;  /* No. of current attaches */  
    ...  
};  

System V共享内存常用API

#include <sys/ipc.h>
#include <sys/shm.h>
/*
创建一个新的内存共享区或者访问一个已经存在的共享内存区
返回共享内存区标识符
*/
int shmget(key_t key, size_t size, int shmflg);
/*
创建或打开一个共享内存区后,调用shmat把它连接到调用进程的地址空间
*/
void *shmat(int shmid, const void *shmaddr,int shmflg);
/*
</pre><pre name="code" class="cpp" style="font-size: 14px;">当一个进程完成某个共享内存区的使用时,调用shmdt断开这个内存区
*/
int shmdt(const void *shmaddr);
/*
对内存区进行多种操作
cmd取值:
IPC_RMID:从系统中删除由shmid标识的共享内存区并拆除它
IPC_SET:给指定的共享内存区设置其shmid_ds结果成员
IPC_STAT:通过buff参数向调用者返回所指定共享内存区当前的shmid_ds结构
*/
int shmctl(int shmid, int cmd, struct shmid_ds *buf);

调用shmget函数使用指定的路径名和长度创建一个共享内存区,如下:

int shmget(key_t key, size_t size, int shmflg);

 创建共享内存,并将该内存的内容初始化为0

   打开一个已经存在共享内存, 如果打开时不知道共享内存的大小, 可以将size指定为0, shmflg可以指定为0(按照默认的权限打开);    

参数:

   key:这个共享内存段名字;

   size:共享内存大小(bytes);

   shmflg:用法类似msgget中的msgflg参数;

返回值:

   成功返回一个非负整数,即该共享内存段的标识码;失败返回-1

/**示例: 创建并打开一个共享内存 **/  
int main(int argc,char **argv)  
{  
    const int SHM_SIZE = 1024;  
    int shmid = shmget(0x1234, SHM_SIZE, 0666|IPC_CREAT);  
    if (shmid == -1)  
        err_exit("shmget error");  
    cout << "share memory get success" << endl;  
}  

shmat

void *shmat(int shmid, const void *shmaddr, int shmflg);

 连接到本进程地址空间, 成功连接之后, 对该内存的操作就与malloc来的一块内存非常类似了, 而且如果这块内存中有数据, 则就可以直接将其中的数据取出来。

参数:

   shmaddr:指定连接的地址(大小不知道的话推荐使用NULL)

   shmflg:一般指定为0, 表示可读,可写; 而它的另外两个可能取值是SHM_RND和SHM_RDONLY(见下)

返回值:

   成功返回一个指针,指向共享内存起始地址;失败返回(void *) -1


注册 Vultr VPS 送你10美金 免费玩4个月