加入收藏 | 设为首页 | 会员中心 | 我要投稿 应用网_丽江站长网 (http://www.0888zz.com/)- 科技、建站、数据工具、云上网络、机器学习!
当前位置: 首页 > 服务器 > 搭建环境 > Linux > 正文

Linux内存管理之mmap分析

发布时间:2022-07-15 16:28:36 所属栏目:Linux 来源:互联网
导读:一. mmap系统调用 1. mmap系统调用 mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。munmap执行相反的操作,删除特定地址区域的对象映射。 采用共享内存通信的一个显
  一. mmap系统调用
 
  1. mmap系统调用    
 
  mmap将一个文件或者其它对象映射进内存。文件被映射到多个页上,如果文件的大小不是所有页的大小之和,最后一个页不被使用的空间将会清零。munmap执行相反的操作,删除特定地址区域的对象映射。
 
  采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。
 
  用法:
 
  #include <sys/mman.h>
 
  void *mmap(void *start, size_t length, int prot, int flags,
 
  int fd, off_t offset);
 
  int munmap(void *start, size_t length);
 
  返回说明:
 
  成功执行时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED[其值为(void *)-1],munmap返回-1。errno被设为以下的某个值
 
  EACCES:访问出错
 
  EAGAIN:文件已被锁定,或者太多的内存已被锁定
 
  EBADF:fd不是有效的文件描述词
 
  EINVAL:一个或者多个参数无效
 
  SIGBUS:试着访问不属于进程的内存区
 
  参数:
 
  start:映射区的开始地址。
 
  length:映射区的长度。
 
  prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
 
  MAP_FIXED //使用指定的映射起始地址,如果由start和len参数指定的内存区重叠于现存的映射空间,重叠部分将会被丢弃。如果指定的起始地址不可用,操作将会失败。并且起始地址必须落在页的边界上。
 
  MAP_SHARED //与其它所有映射这个对象的进程共享映射空间。对共享区的写入,相当于输出到文件。直到msync()或者munmap()被调用,文件实际上不会被更新。
 
  MAP_PRIVATE //建立一个写入时拷贝的私有映射。内存区域的写入不会影响到原文件。这个标志和以上标志是互斥的,只能使用其中一个。
 
  MAP_DENYWRITE //这个标志被忽略。
 
  MAP_EXECUTABLE //同上
 
  MAP_NORESERVE //不要为这个映射保留交换空间。当交换空间被保留,对映射区修改的可能会得到保证。当交换空间不被保留,同时内存不足,对映射区的修改会引起段违例信号。
 
  MAP_LOCKED //锁定映射区的页面,从而防止页面被交换出内存。
 
  MAP_GROWSDOWN //用于堆栈,告诉内核VM系统,映射区可以向下扩展。
 
  MAP_ANONYMOUS //匿名映射,映射区不与任何文件关联。
 
  MAP_ANON //MAP_ANONYMOUS的别称,不再被使用。
 
  MAP_FILE //兼容标志,被忽略。
 
  fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1。
 
  offset:被映射对象内容的起点。
 
  2. 系统调用munmap()
 
  #include <sys/mman.h>
 
  int munmap( void * addr, size_t len ) 该调用在进程地址空间中解除一个映射关系,addr是调用mmap()时返回的地址,len是映射区的大小。当映射关系解除后,对原来映射地址的访问将导致段错误发生。
 
  3. 系统调用msync()
 
  #include <sys/mman.h>
 
  int msync ( void * addr , size_t len, int flags) 一般说来,进程在映射空间的对共享内容的改变并不直接写回到磁盘文件中,往往在调用munmap()后才执行该操作。可以通过调用msync()实现磁盘上文件内容与共享内存区的内容一致。
 
  二. 系统调用mmap()用于共享内存的两种方式
 
  (1)使用普通文件提供的内存映射:适用于任何进程之间;此时,需要打开或创建一个文件,然后再调用mmap();典型调用代码如下:
 
  fd=open(name, flag, mode);
 
  if(fd<0)
 
  ...
 
  ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);
 
  通过mmap()实现共享内存的通信方式有许多特点和要注意的地方
 
  (2)使用特殊文件提供匿名内存映射:适用于具有亲缘关系的进程之间;由于父子进程特殊的亲缘关系,在父进程中先调用mmap(),然后调用fork()。那么在调用fork()之后,子进程继承父进程匿名映射后的地址空间,同样也继承mmap()返回的地址,这样,父子进程就可以通过映射区域进行通信了。注意,这里不是一般的继承关系。一般来说,子进程单独维护从父进程继承下来的一些变量。而mmap()返回的地址,却由父子进程共同维护。 对于具有亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映射的方式。此时,不必指定具体的文件,只要设置相应的标志即可.

(编辑:应用网_丽江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读