Chinaunix首页 | 论坛 | 博客
  • 博客访问: 596109
  • 博文数量: 178
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 2162
  • 用 户 组: 普通用户
  • 注册时间: 2009-05-12 20:06
文章分类

全部博文(178)

文章存档

2011年(1)

2010年(94)

2009年(86)

我的朋友

分类:

2009-12-17 08:42:36

I:Linux内存映射: mmap[摘自


Linux提供了内存映射函数mmap, 它把文件内容映射到一段内存上(准确说是虚拟内存上), 通过对这段内存的读取和修改, 实现对文件的读取和修改, 先来看一下mmap的函数声明:
  • 头文件:
  • 原型: void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offsize);
  • 返回值: 成功则返回映射区起始地址, 失败则返回MAP_FAILED(-1).
  • 参数:
    • addr: 指定映射的起始地址, 通常设为NULL, 由系统指定.
    • length: 将文件的多大长度映射到内存.
    • prot: 映射区的保护方式, 可以是:
      • PROT_EXEC: 映射区可被执行.
      • PROT_READ: 映射区可被读取.
      • PROT_WRITE: 映射区可被写入.
      • PROT_NONE: 映射区不能存取.
    • flags: 映射区的特性, 可以是:
      • MAP_SHARED: 对映射区域的写入数据会复制回文件, 且允许其他映射该文件的进程共享.
      • MAP_PRIVATE: 对映射区域的写入操作会产生一个映射的复制(copy-on-write), 对此区域所做的修改不会写回原文件.
      • 此外还有其他几个flags不很常用, 具体查看linux C函数说明.
    • fd: 由open返回的文件描述符, 代表要映射的文件.
    • offset: 以文件开始处的偏移量, 必须是分页大小的整数倍, 通常为0, 表示从文件头开始映射.

    下面说一下内存映射的步骤:

  • 用open系统调用打开文件, 并返回描述符fd.
  • 用mmap建立内存映射, 并返回映射首地址指针start.
  • 对映射(文件)进行各种操作, 显示(printf), 修改(sprintf).
  • 用munmap(void *start, size_t lenght)关闭内存映射.
  • 用close系统调用关闭文件fd.

注意事项:

在修改映射的文件时, 只能在原长度上修改, 不能增加文件长度, 因为内存是已经分配好的.



II:[摘自]

内存映射文件(mmap)

内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文

件,就像操作进程空间里的地址一样了,比如使用memcpy等内存操作的函数。这种方法能

够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比

普通IO效率要高。另外,UNIX把它做为内存共享来设计的。

UNIX中,头文件中有与此相关的函数定义。mman==super man :)

1、创建一个内存映射区域

void *mmap(void *addr, size_t len, int prot, int flag, int filedes, off_t off);



addr

映射区首地址,你想自己定义的时候使用。一般使用NULL,然后系统自动分配一个合适地址。

len

映射的长度, 单位byte

prot

说明映射区访问属性:读、写、执行、不可访问

                    PROT_READ,PROT_WRITE,PROT_EXEC,PROT_NONE

不能超越它所映射的文件的权限

flag

MAP_SHARED 这个标志说明文件映射是共享的,也就是说进程改变了内存映射,也就会影响到文件。

MAP_PRIVATE 这个标志说明文件映射不共享,打开文件映射的进程只能改变的是这个文件的一个副本。

filedes

文件描述符号

off

隐射位置的偏移量,设置为0的话,就映射文件的0-len个字节

返回

映射区域的首地址

2、取消文件映射

int munmap(caddr_t addr,size_t len);



addr

内存隐射的地址。mmap返回的地址。

len

隐射的字节数。

返回

成果0,失败负

使用MAP_PRIVATE的映射改变将不被写回文件。

3、内存映射和文件的同步

int msync(void *addr, size_t len,int flags);



addr

内存映射地址

len

长度

flags

MS_ASYNC,MS_SYNC,MS_INVALIDATE

MS_ASYNC,异步写,调用后就返回不等待写完,MS_SYNC则等待写完才返回。

MS_INVALIDATE,写完之后,内存映射中与文件不同的数据将无效,取而代之的是文件中的数据。

返回

成功0,失败负

4、创建共享内存区

这个信号量比较相同。

int shm_open(const char *name ,into flag, mode_t mode);

对比:

sem_t *sem_open(const char *name,int oflag,/*mode_t mode,unsigned int value*/);

这个地方就可以解释sem_open函数的文件名有什么用了。使用shem_open创建共享文件,

使用mmap使内存这个文件映射,实现共享内存,然后再使用信号量来同步。这个搭配可算是完美!



name

共享区名,需要绝对路径

flag

open文件一样,O_RDONLY O_RDWR O_CREAT O_TRUNC

mode

权限位置,和文件相同。只能在O_CREAT下使用

返回

成功返回一个文件描述字,失败负

既然它是一种文件,那么我们对文件操作的函数, fstat lstat read wirte ftruncate 这些函数都可以尝试着对他使用一把。不成功便成人嘛!

5、删除共享内存区

int  shm_unlink(const char *name);

阅读(2687) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~