博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
UNIX网络编程——Posix共享内存区和System V共享内存区
阅读量:4010 次
发布时间:2019-05-24

本文共 3648 字,大约阅读时间需要 12 分钟。

1.Posix共享:

Posix提供了两种在无亲缘关系进程间共享内存区的方法:

(1)内存映射文件:先有open函数打开,然后调用mmap函数把得到的描述符映射到当前进程地址空间中的一个文件。

(2)共享内存区对象:先有shm_open打开一个Posix IPC名字(也可以是文件系统中的一个路径名),然后调用mmap将返回的描述符映射到当前进程的地址空间。

两种方法多需要调用mmap,差别在于作为mmap的参数之一的描述符的获取手段。

Posix共享内存区对象

  Posix共享内存区涉及以下两个步骤要求:

(1)指定一个名字参数调用shm_open,以创建一个新的共享内存区对象或打开一个已经存在的共享内存区对象。

(2)调用mmap把这个共享内存区映射到调用进程的地址空间。

采用Posix共享内存实现给一个共享的计数器持续加1,它由多个进程给存放在共享内存区中的某个计数器持续加1。将计数器放在一个共享内存区中,并用一个有名信号量来同步。

下面看一个例子:

创建并初始化共享内存区和信号量的程序如下:server1.c

#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)//计数器结构体struct shmstruct{ int count;};//同步有名信号量sem_t *mutex;int main(int argc,char *argv[]){ int fd; struct shmstruct *ptr; if(argc != 3) { printf("usage: server1
.\n"); exit(0); } //防止所需共享内存区对象已经存在 shm_unlink(argv[1]); //创建一个新的共享内存区对象 if((fd = shm_open(argv[1],O_RDWR | O_CREAT | O_EXCL,FILE_MODE)) == -1) { perror("shm_open error"); exit(-1); } //指定新创建的共享内存区对象的大小 ftruncate(fd,sizeof( struct shmstruct)); //将新创建的共享内存区映射到调用进程的地址空间 if((ptr = mmap(NULL,sizeof(struct shmstruct),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED) { perror("mmap error"); exit(-1); } //关闭对象描述符 close(fd); //防止所需的信号量已经存在 sem_unlink(argv[2]); //创建有名信号量,作为互斥锁用 if((mutex = sem_open(argv[2],O_CREAT|O_EXCL,FILE_MODE,1)) == SEM_FAILED) { perror("sem_open error"); exit(-1); } //关闭信号量 sem_close(mutex); exit(0);}
给存放在共享内存区中的一个计数器加1程序如下:client1.c
#include 
#include
#include
#include
#include
#include
#include
#include
#include
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)struct shmstruct{    int     count;};sem_t  *mutex;int main(int argc,char *argv[]){    int     fd,i,nloop;    pid_t   pid;    struct shmstruct *ptr;    if(argc != 4)    {        printf("usage: client1
<#loops>.\n");        exit(0);    }    nloop = atoi(argv[3]);        //打开共享内存区    if((fd = shm_open(argv[1],O_RDWR,FILE_MODE)) == -1)    {        perror("shm_open error");        exit(0);    }        //将共享内存区映射到进程地址空间    if((ptr = mmap(NULL,sizeof(struct shmstruct),PROT_READ | PROT_WRITE,MAP_SHARED,fd,0)) == MAP_FAILED)    {        perror("mmap error");        exit(-1);    }    close(fd);        //打开信号量    if((mutex = sem_open(argv[2],0)) == SEM_FAILED)    {        printf("sem_open error");        exit(-1);    }    pid = getpid();    for(i=0;i
count++);        sem_post(mutex); //释放信号量    }    exit(0);}

2.system V 共享内存:

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

System V 共享内存区API

  使用共享内存的流程:
   1.进程必须首先分配它。
   2.随后需要访问这个共享内存块的每一个进程都必须将这个共享内存绑定到自己的地址空间中。
   3.当完成通信之后,所有进程都将脱离共享内存,并且由一个进程释放该共享内存块。

System V 与Posix 共享内存区

  二者的差别是:

(1)Posix共享内存区是先调用shm_open然后再调用mmap,System V 共享内存区是先调用shmget再调用shmat。

(2)Posix共享内存区对象的大小可在任何时刻通过ftruncate修改,而System V 共享内存区对象的大小是在调用shmget创建时固定下来的。

调用shmget函数使用指定的路径名和长度创建一个共享内存区,程序如下:
#include 
#include
#include
#include
#include
#define SVSHM_MODE (SHM_R | SHM_W | SHM_R>>3 | SHM_R>>6)int main(int argc,char *argv[]){ int c,id,oflag; char *ptr; size_t length; oflag = SVSHM_MODE | IPC_CREAT; while(( c = getopt(argc,argv,"e")) != -1) { switch(c) { case 'e': oflag |= O_EXCL; break; } } if (optind != argc -2) { printf("usage: shmget [-e]
.\n"); exit(0); } length = atoi(argv[optind + 1]); //创建由用户指定其名字和大小的共享内存区 id = shmget(ftok(argv[optind],0),length,oflag); //把该内存区连接到当前进程的地址空间 ptr = shmat(id,NULL,0); exit(0);}

转载地址:http://jwifi.baihongyu.com/

你可能感兴趣的文章
getpeername,getsockname
查看>>
让我做你的下一行Code
查看>>
浅析:setsockopt()改善程序的健壮性
查看>>
关于对象赋值及返回临时对象过程中的构造与析构
查看>>
VS 2005 CRT函数的安全性增强版本
查看>>
SQL 多表联合查询
查看>>
Visual Studio 2010:C++0x新特性
查看>>
drwtsn32.exe和adplus.vbs进行dump文件抓取
查看>>
cppcheck c++静态代码检查
查看>>
CLOSE_WAIT和TIME_WAIT
查看>>
在C++中使用Lua
查看>>
在Dll中调用自身的位图资源
查看>>
IP校验和详解
查看>>
C++中使用Mongo执行count和distinct运算
查看>>
一些socket的编程经验
查看>>
socket编程中select的使用
查看>>
C++获取文件大小常用技巧分享
查看>>
未来5年大机遇:做贩卖多巴胺的超级玩家
查看>>
关于AIS编码解码的两个小问题
查看>>
GitHub 万星推荐:黑客成长技术清单
查看>>