共享内存
2011年06月27日
一、system v
共享内存允许多个进程共享同一块物理内存空间来实现进程之间的信息交换,其特点是没有中间环节,直接将共享的内存页面通过附接,映射到相互通信的进程各自的虚拟地址空间中,从而使多个进程可以直接访问同一个物理内存页面,如同访问自己的私有空间一样(但实质上不是私有的而是共享的)。如果一个进程向这段共享内存写了数据,所做的改动会立刻被有访问同一段共享内存的其他进程看到。要注意的是共享内存本身没有提供任何同步功能。
一、SystemV共享内存
1、 获得共享内存
int shmget( key_t key, size_t size, int shmflg );
成功返回内存id,失败返回-1。
Key
一般用ftok获得
#include
#include
key_t ftok(const char *pathname, int proj_id);
size
内存大小,向上取整,单位是页,一页大小是4096个字节。所以如果一段进程只申请一块只有一个字节的内存,内存也会分配整整一页。
Shmflg
IPC_CREAT:如果内核中没有此共享内存,则创建它。 如果已经存在,则返回已存在的具有相同关键字值的共享内存的内部标识符
IPC_EXCL当和IPC_CREAT一起使用时,如果内核中没有此共享内存,则创建它。如果此共享内存已经存在,则失败。
在实验中,可以使用0666|IPC_CREAT,表示任意进程可读可写。
2、 将共享内存映射到进程的地址空间
void *shmat( int shmid, const void * shmaddr, int shmflg );
成功返回地址,失败返回-1.
shmid
共享存储区的描述符
Shmaddr
用户提供的共享存储区附接的虚地址,一般取0,表示由系统选择。
Shmflg
规定了对该存储区的操作权限,一般写0,表示可读可写。
3、 断开共享内存和进程的映射
int shmdt(const void *shmaddr);
正确返回0,失败返回-1。
4、 移除共享内存
shmctl(int shmid, int cmd, struct shmid_ds *buf)
正确返回0,失败返回-1。
shmid
共享存储区的内部标识符
Cmd
移除写 PC_RMID
Buf
取0。
例如:shmctl(shmid,IPC_RMID,0);
下面增加一些字符处理的函数
1、以追加的方式写入
#include
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
The strcat() function appends the src string to the dest string, overwriting the null byte ('\0') at the end of dest, and then adds a terminating null byte. The strings may not overlap, and the dest string must have enough space for the result.
char* strncat(char *dest, const char *src, size_t n)
{
size_t dest_len = strlen(dest);
size_t i;
for (i = 0 ; i
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
3、覆盖的方式
#include
void *memset(void *s, int c, size_t n);
The memset() function fills the first n bytes of the memory area pointed to by s with the constant byte c.
二、posix
1、 打开或创建一个共享内存区
int shm_open(const char *name,int oflag,mode_t mode);
name
路径
Oflag
O_RDONLY、O_RDWR、O_CREAT(已经存在,就直接打开)、O_EXCL(已经存在返回错误)、O_TRUNC(已经存在就清空)。
Mode
指定权限位,它指定O_CREAT标志的前提下使用。
2、 调整共享内存区的大小
int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
可以用于文件和共享内存,成功返回0,失败返回-1。
3、 把共享内存区映射到进程
void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
addr参数用于指定映射存储区的起始地址。通常将其设置为NULL。
length是要映射的字节数。
prot参数说明对映射存储区的保护要求。PROT_READ(映射区可读), PROT_WRITE(映射区可写), PROT_EXEC(映射区可执行)任意组合的按位或,也可以是PROT_NONE(映射区不可访问)。对指定映射存储区的保护要求不能超过文件open模式访问权限。
Flags: MAP_SHARED,一个进程对映射的内存做了修改,另一个进程也会看到这种变化。
4、 同步
int msync(void *addr,size_t len,int flags);
如果我们修改了内存映射到某个文件的内存区中某个位置的内容,那么内核将在稍后某个时刻相应地更新文件。然而有时候我们希望确信硬盘上的文件内容与内存映射区中的文件内容一致,于是调用msync()来写回磁盘,实现磁盘上文件内容与共享内存区的内容一致。
若成功则返回0,若出错则返回-1
addr 指向映射存储区的起始地址
len 映射的字节
flags:
MS_ASYNC(执行异步写),一调用,函数就立刻返回,在后台写回文件
MS_SYNC(执行同步写),直到写回文件,函数才会返回
MS_INVALIDATE(使其他进程的映射区的数据失效),一般不用
一般只使用MS_SYNC
5、取消映射
int munmap(caddr_t addr,size_t len);
会执行写回磁盘的操作。然后取消映射。
6、删除一个共享内存区
int shm_unlink(const char *name);
成功返回0,出错返回-1
mmap三种使用方式[/b]
void *mmap(void *addr, size_t length, int prot, int flag, int fd, off_t off);[b]
(1)内存映射I/O,将一个普通文件映射进内存:适用于任何进程之间; 此时,需要打开或创建一个文件,然后再调用mmap();典型调用代码如下:
fd=open(name, flag, mode);
if(fd内存映射:适用于具有亲缘关系的进程之间; 由于父子进程特殊的亲缘关系,在父进程中先调用mmap(),然后调用fork()。
那么在调用fork()之后,子进程继承父进程匿名映射后的地址空间,同样也继承mmap()返回的地址,这样,父子进程就可以通过映射区域进行通信了。
对于具有亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映射的方式。此时,不必指定具体的文件,只要设置相应的标志即可。
Ptr = mmap(0,len, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS,-1,0);
(3)共享内存映射,见上。
发表评论
-
认识JVM
2012-01-20 02:40 740认识JVM 2011年06月18日 ... -
DELPHI VCL组件 TTreeList, Listview和Treeview相结合的多列树控件
2012-01-20 02:40 1608DELPHI VCL组件 TTreeList, Listvie ... -
使用qemu调试linux内核
2012-01-20 02:40 1029使用qemu调试linux内核 2011年03月20日 ... -
.net Framework 4 中的新增功能
2012-01-20 02:40 799.net Framework 4 中的新增功能 2010年0 ... -
《Linux内核设计与实现》ch14
2012-01-20 02:40 712《Linux内核设计与实现 ... -
Flex 86道题(好好学习一下)
2012-01-19 10:24 577Flex 86道题(好好学习一 ... -
修复工具类
2012-01-19 10:23 556修复工具类 2011年05月08日 ... -
Windows系统的Regsvr32
2012-01-19 10:23 570Windows系统的Regsvr32 2011 ... -
as3面试题
2012-01-19 10:23 516as3面试题 2011年09月13日 ... -
“该内存不能为读写”解决方法
2012-01-17 03:04 508“该内存不能为读写” ... -
全局内存
2012-01-17 03:04 566全局内存 2011年06月07日 ... -
内存绘图
2012-01-17 03:04 584内存绘图 2010年10月07日 经常出现图形闪烁的 ... -
获取内存中可执行文件的PE结构--导入表
2012-01-17 03:04 1456获取内存中可执行文件的PE结构--导入表 2012年01月1 ... -
应该如何指导小学生自己批改作文
2012-01-16 01:35 558应该如何指导小学生自己批改作文 2010年10月14日 ... -
作文评语中如何育人
2012-01-16 01:35 719作文评语中如何育人 20 ... -
小学作文评语原则及思考
2012-01-16 01:35 559小学作文评语原则及思 ... -
何培养小学生作文批改能力
2012-01-16 01:35 615何培养小学生作文批改能力 2010年10月14日 文评改 ... -
如何批改小学生作文2
2012-01-16 01:35 456如何批改小学生作文2 2009年10月08日 我的妈妈 ... -
转:敏捷开发中的code review-荒原-iteye技术网站
2012-01-11 01:10 504转:敏捷开发中的code revi ...
相关推荐
共享内存,顾名思义就是允许两个不相关的进程访问同一个逻辑内存,共享内存是两个正在运行的进程之间共享和传递数据的一种非常有效的方式。不同进程之间共享的内存通常为同一段物理内存。进程可以将同一段物理内存...
ShareMemLib将共享内存代码封装成lib,定义了发送者和监听者 两个进程在实例化ShareMemory时指定相同的map,并指定当前为发送者或监听者 发送者负责发送消息,监听者负责接受消息(监听者务必实现接受消息处理方法) ...
要使用共享内存,应该有如下步骤: 1.开辟一块共享内存 shmget() 2.允许本进程使用共某块共享内存 shmat() 3.写入/读出 4.禁止本进程使用这块共享内存 shmdt() 5.删除这块共享内存 shmctl()或者命令行下ipcrm ftok...
C#共享内存的实例,附源码和工程文件。 网上有C#的共享内存类,不过功能太简单了。 故,对此进行了改进。通过利用共享内存的一部分空间来存储当前内存中存储的数据信息(count和length),完成了对内存读写功能的...
C#操作共享内存读写工程、C#操作共享内存读写工程、C#操作共享内存读写工程
程序间共享内存,用于数据交换,非常强大的示例,解决你进程间数据共享的问题 不错,解决了传输问题,可以共享N个字符串。整数等类型 改造一下,进程通讯就可以用了 我用它做串口数据共亭。。不错。。 挺好用的我...
VS2005 C# 共享内存 源代码
在使用共享内存的程序异常退出时,由于没有释放掉共享内存,在调试时会出现错误。您可以使用shell命令来查看与释放已经分配的共享内存,下面将详细说明如何进行查看和释放分配的共享内存的方法。
C++共享内存进程间通信 FileMapping用于进程间快速通信
利用共享内存实现进程间的通信,可用于操作系统的教学。(原创)
共享内存,简单易懂的学习共享内存, 是学习共享内存的入门
共享内存方式实现进程间通信。详细看我的博客:http://blog.csdn.net/pengguokan/article/details/8921346
C 共享内存 2个程序之间传输数据。 内部有2个C文件,x1.c是共享内存的读取程序,x2.c是共享内存的写入程序
共享内存 共享内存数据库 数据库 Linux技术文档 Linux 任务书 共享内存 共享内存数据库 数据库 Linux技术文档 Linux 任务书
此代码进行了共享内存的通信演示。 此演示非常简单,只是演示如何使用,没有考虑性能、方式等,如果需要拿到真正的代码中使用,则需要考虑其它额外的工作,比如方式、效率等。 使用vc6.0
易语言读写共享内存例程源码.rar
QT共享内存QSharedMemory读写例子
易语言读写共享内存例程源码,读写共享内存例程,CreateFileMappingA,MapViewOfFile,UnmapViewOfFile,CloseHandle,OpenFileMappingA
代码实现了共享内存和信号量的结合,实现进程间通信及其同步问题。通过此代码可以理解共享内存及信号量基本函数的使用及实现原理。
Qt共享内存实现进程间通信(QSharedMemory) 源代码