进程间通信-共享内存
来源:互联网 发布:云计算应用介绍 编辑:程序博客网 时间:2024/06/03 19:16
共享存储允许两个或多个进程共享一个给定的存储区。因为数据不需要在客户进程和服务器进程之间复制,所以这是最快的一种IPC。使用共享存储时要掌握的唯一窍门是,在多个进程之间同步访问一个给定的存储区。若服务器进程正在将数据放入共享存储区,则在它做完这一操作之前,客户进程不应当去取这些数据。通常,信号量用于同步共享存储访问,也可以用记录锁和互斥量。
System V 共享内存区
调用的第一个函数通常是shmget,它获得一个共享存储标识符
#include<sys/shm.h>int shmget(key_t key,size_t size,int flag);返回值:若成功,返回共享存储ID,若失败,返回-1;
参数size是该共享存储段的长度,以字节为单位。实现通常将其向上取为系统页长的整数倍。若应用指定的size值并非系统页长的整数倍,那么最后一页的余下部分是不可使用的。如果正在创建一个新段,那么必须指定其size。如果正在引用一个现存的段,则将其size指定 为0。当创建一个新段时,段内的内容初始化为0。
shmctl函数对共享存储段执行多种操作
#incldue<sys/shm.h>int shmctl(int shmid,int cmd,struct shmid_ds* buf);返回值:若成功,返回0;若出错,返回-1;
IPC_STAT 取此段的shmid_ds结构,并将它存放在buf指向的结构中
IPC_SET 将字段shm_perm.uid、shm_perm.gid、shm_perm.mode 从buf指向的结构复制到与这个共享存储段相关的shmid_ds结构中。
IPC_RMID 从系统中删除该共享存储段。
Linux和Solaris提供了另外两种命令
SHM_LOCK 在内存中对共享存储段加锁,此命令只能有超级用户执行
SHM_UNLOCK 解锁共享存储段,此命令只能由超级用户执行
一旦创建了一个共享存储段,进程就可以调用shmat将其连接到它的地址空间。
#include<sys/shm.h>void* shmat(int shmid,const void* addr,int flag);返回值:若成功,返回指向共享存储段的指针;若出错,返回-1;
共享存储段连接到调用进程的哪个地址上与addr参数以及flag中是否指定SHM_RND位有关。
如果addr为0,则此段连接到由内核选择的第一个可用地址上。这是推荐的使用方法。
如果addr非0,并且没有指定SHM_RND,则此段连接到addr指定的地址上。
如果 addr 非0, 并且指定了SHM_RND, 则此段连接到 (addr-(addr mod SHMLBA)) 所表示的地址上。SHM_RND 命令的意思是 “取整’. SHMLBA的意思是 “低边界地址倍数”,它总是2的乘方。 该算式是将地址向下取最近1个SHMLBA的倍数.
除非只在一种硬件上运行应用程序(这在当今是不大可能的),否则不应指定共享存储段所连接到的地址。而是应当指定addr为0,以便由系统选择地址。
如果在flag中指定SHM_RDONLY,则以只读方式连接此段,否则以读写方式连接此段。
当对共享存储段的操作已经结束,则调用shmdt与该段分离。注意,这并不从系统中删除其标识符以及其相关的数据结构。该标识符仍然存在,直到某个进程带IPC_RMID命令的调用shmctl特地删除它为止。
#include<sys/shm.h>int shmdt(const void* addr);返回值:若成功,返回0;若出错,返回-1;
下面是运用共享存储实现进程间通信的例子
//shmwrite.c#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/shm.h>#include<string.h>#include<errno.h>#define MAXLEN 1024int main(){ int shmid; char buf[MAXLEN]; int n; void* shmaddr; int count=0; if((shmid=shmget((key_t)1234,MAXLEN,0666|IPC_CREAT))<0) //创建共享存储区 { fprintf(stderr,"shmget error:[%s]\n",strerror(errno)); exit(1); } if((shmaddr=shmat(shmid,0,0))<0) //将共享存储区连接到地址空间 { fprintf(stderr,"shmat error:[%s]\n",strerror(errno)); exit(1); } while(fgets(buf,MAXLEN,stdin)!=NULL) { memcpy(shmaddr,buf,MAXLEN); //写入到共享存储区 } shmctl(shmid,IPC_RMID,0); exit(0);}
//shmread.c#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/shm.h>#include<string.h>#include<errno.h>#define MAXLEN 1024int main(){ int shmid; char buf[MAXLEN]; int n; void* shmaddr; if((shmid=shmget((key_t)1234,0,0))<0) //引用已创建的共享存储区 { fprintf(stderr,"shmget error:[%s]\n",strerror(errno)); exit(1); } if((shmaddr=shmat(shmid,0,SHM_RDONLY))<0) //将共享存储区连接到内存空间 { fprintf(stderr,"shmat error:[%s]\n",strerror(errno)); exit(1); } while(1) { sleep(5); memcpy(buf,shmaddr,MAXLEN); //从共享存储区读取数据 printf("%s",buf); } shmdt(shmaddr); exit(0);}
- 进程间通信-共享内存
- 进程间通信---共享内存
- 进程间通信--共享内存
- 进程间通信--共享内存
- 进程间通信-共享内存
- 进程间通信共享内存
- 进程间通信-共享内存
- 进程间通信---共享内存
- 进程间通信----共享内存
- 【进程间通信】共享内存
- 进程间通信共享内存
- 进程间通信----共享内存
- 进程间通信---共享内存
- 进程间通信--------共享内存
- 进程间通信---共享内存
- 进程间通信-共享内存
- 进程间通信----共享内存
- 进程间通信---共享内存
- 解决手机自带浏览器上,用rem单位,内容超出屏幕宽度问题!(rem计算不准)
- 12、二叉树的实现及应用-表达式处理
- hdu 1213 基础并查集
- python -m 与 pybot ,结合robot库,采用robotframework框架运行脚本
- 文章标题
- 进程间通信-共享内存
- 生产者和消费者(PV操作、共享内存)
- [Hnoi2010]Bounce 弹飞绵羊
- ActiveMQ的安装及使用
- imagenet2012数据集
- 常见的代码托管平台
- Android O(8.0)创建桌面快捷方式
- ANSYS_CFX
- 运维老鸟教你安装centos6.5如何选择安装包