UNIX/Linux进程间通信IPC系列(七)共享内存区

共享存储


共享存储允许两个或更多进程共享一给定的存储区。因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC。

一旦这样的内存区映射到共享它的进程的地址空间,这些进程间数据的传递就不再涉及内核。但往该共享内存区存放信息或从中取走信息的进程间需要某种形式的同步。(通常,信号量记录锁被用来实现对共享存储访问的同步)

 

shmget函数

shmget函数创建一个新的共享内存区,或者访问一个已存在的共享内存区。

#include <sys/shm.h>

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

返回值是一个称为共享内存区标识符的整数,其他三个shmXXX函数就用它来指代这个内存区。

 

参数key既可以是ftok的返回值,也可以是IPC_PRIVATE

参数size是指定内存区的大小。(若访问已存在的内存区,则size应为0)

参数oflag是读写权限值的组合。

当实际操作为创建一个新的共享内存区时,该内存区被初始化为size字节的0。

 

shmat函数

由shmget函数创建或打开一个共享内存区后,通过调用shmat把它附接到调用进程的地址空间。

#include <sys/shm.h>

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

参数shmid是由shmget返回的标识符。

shmat的返回值是所指定的共享内存区在调用进程内的起始地址。(一般把参数shmaddr置为NULL,让系统替调用者选择地址)

参数flag可以指定SHM_RDONLY值,它限定只读访问。(默认可同时读写)

 

shmdt函数

当一个进程完成某个共享内存区的使用时,它可以调用shmdt断接这个内存区。

#include <sys/shm.h>

int  shmdt (const void* shmaddr) ;

当一个进程终止时,它当前附接着的所有共享内存区都自动断接掉。

注意,本函数只是断开关联,并不删除所指定的共享内存区。删除工作通过以IPC_RMID命令调用shmctl完成。(XSI IPC都是随内核持续的)

 

shmctl函数

shmctl提供了对一个共享内存区的多种操作。

#include <sys/shm.h>

int  shmctl (int shmid,  int cmd, struct shmid_ds* buff) ;

参数cmd:

IPC_RMID 从系统中删除该共享存储段。因为每个共享存储段有一个连接计数器,所以除非使用该段的最后一个进程终止或与该段脱接,否则不会实际上删除该存储段。但不管此段是否仍在使用,该段标识符立即被删除,所以不能再用shmat与该段连接。


【示例】

//共享内存IPC简单示例
//
//使用方法:程序名 路径名 消息内容
//
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h> 
#include <string.h>

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

int 
main(int argc, char** argv)
{
    int    shmid ;           //共享内存区的标识符
    size_t shmSize = 512  ;  //共享内存的大小
    char*  shmaddr ;         //共享内存的指针    
     int  i = 0 ;

    if (argc != 3)
    {
        perror("parameter error!\n") ;
        exit(0) ;
    }
    
    //创建共享内存
    shmid = shmget(ftok(argv[1], 0), shmSize, IPC_CREAT) ;

    //获取共享内存的指针(把共享内存映射到本进程地址空间)
    shmaddr = shmat(shmid, NULL, 0) ;

    //向共享内存中写入数据
    strcpy(shmaddr, argv[2]) ;

    //断开与共享内存的连接
    shmdt(shmaddr) ;
    exit(0) ;
}

//共享内存IPC简单示例
//访问共享内存
//
//使用方法:程序名 同一路径名 消息内容
//
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h> 
#include <sys/ipc.h>
#include <sys/shm.h>
#include <fcntl.h>

int 
main(int argc, char** argv)
{
    int   shmid ;           //共享内存区的标识符
    key_t shmkey ;          //共享内存区的key
    char  msgbuf[512] ;     //存储从共享存储区提取的消息
    char*  shmaddr ;        //共享内存的指针  
 
    if (argc != 2)
    {
        perror("parameter error!\n") ;
        exit(0) ;
    }
    
    //打开共享内存
    shmid = shmget(ftok(argv[1], 0), 0, 0) ;

    //把共享内存映射到本进程地址空间
    shmaddr = shmat(shmid, NULL, 0) ;

    //读取共享内存中的消息
    printf("The message in the share memory : %s\n", shmaddr) ;

    //断开与共享内存的连接
    shmdt(shmaddr) ;
    //删除共享内存
    shmctl(shmid, IPC_RMID, NULL) ;

    exit(0) ;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值