Linux内存管理之mmap详解
来源:互联网 发布:国家网络安全法实名制 编辑:程序博客网 时间:2024/05/17 01:21
一.
1.
当使用mmap映射文件到进程后,就可以直接操作这段虚拟地址进行文件的读写等操作,不必再调用read,write等系统调用.但需注意,直接对该段内存写时不会写入超过当前文件大小的内容.
采用共享内存通信的一个显而易见的好处是效率高,因为进程可以直接读写内存,而不需要任何数据的拷贝。对于像管道和消息队列等通信方式,则需要在内核和用户空间进行四次的数据拷贝,而共享内存则只拷贝两次数据:一次从输入文件到共享内存区,另一次从共享内存区到输出文件。实际上,进程之间在共享内存时,并不总是读写少量数据后就解除映射,有新的通信时,再重新建立共享内存区域。而是保持共享区域,直到通信完毕为止,这样,数据内容一直保存在共享内存中,并没有写回文件。共享内存中的内容往往是在解除映射时才写回文件的。因此,采用共享内存的通信方式效率是非常高的。
用法:
#include
void
int
int
返回说明:
成功执行时,mmap()返回被映射区的指针,munmap()返回0。失败时,mmap()返回MAP_FAILED[其值为(void
EACCES:访问出错
EAGAIN:文件已被锁定,或者太多的内存已被锁定
EBADF:fd不是有效的文件描述词
EINVAL:一个或者多个参数无效
ENFILE:已达到系统对打开文件的限制
ENODEV:指定文件所在的文件系统不支持内存映射
ENOMEM:内存不足,或者进程已超出最大内存映射数量
EPERM:权能不足,操作不允许
ETXTBSY:已写的方式打开文件,同时指定MAP_DENYWRITE标志
SIGSEGV:试着向只读区写入
SIGBUS:试着访问不属于进程的内存区
参数:
start:映射区的开始地址。
length:映射区的长度。
prot:期望的内存保护标志,不能与文件的打开模式冲突。是以下的某个值,可以通过or运算合理地组合在一起
PROT_EXEC
PROT_READ
PROT_WRITE
PROT_NONE
flags:指定映射对象的类型,映射选项和映射页是否可以共享。它的值可以是一个或者多个以下位的组合体
MAP_FIXED
MAP_SHARED
MAP_PRIVATE
MAP_DENYWRITE
MAP_EXECUTABLE
MAP_NORESERVE
MAP_LOCKED
MAP_GROWSDOWN
MAP_ANONYMOUS
MAP_ANON
MAP_FILE
MAP_32BIT
MAP_POPULATE
MAP_NONBLOCK
fd:有效的文件描述词。如果MAP_ANONYMOUS被设定,为了兼容问题,其值应为-1。
offset:被映射对象内容的起点。
2.
#include
int
该调用在进程地址空间中解除一个映射关系,addr是调用mmap()时返回的地址,len是映射区的大小。当映射关系解除后,对原来映射地址的访问将导致段错误发生。
3.
#include
int
一般说来,进程在映射空间的对共享内容的改变并不直接写回到磁盘文件中,往往在调用munmap()后才执行该操作。可以通过调用msync()实现磁盘上文件内容与共享内存区的内容一致。
二.
- fd=open(name, flag, mode);
- if(fd<</SPAN>0)
-
... - ptr=mmap(NULL, len , PROT_READ|PROT_WRITE, MAP_SHARED , fd , 0);
通过mmap()实现共享内存的通信方式有许多特点和要注意的地方
(2)使用特殊文件提供匿名内存映射:适用于具有亲缘关系的进程之间;由于父子进程特殊的亲缘关系,在父进程中先调用mmap(),然后调用fork()。那么在调用fork()之后,子进程继承父进程匿名映射后的地址空间,同样也继承mmap()返回的地址,这样,父子进程就可以通过映射区域进行通信了。注意,这里不是一般的继承关系。一般来说,子进程单独维护从父进程继承下来的一些变量。而mmap()返回的地址,却由父子进程共同维护。
对于具有亲缘关系的进程实现共享内存最好的方式应该是采用匿名内存映射的方式。此时,不必指定具体的文件,只要设置相应的标志即可.
三.
1.在用户虚拟地址空间中寻找空闲的满足要求的一段连续的虚拟地址空间,为映射做准备(由内核mmap系统调用完成)
下面是struct
- #include <</SPAN>linux/mm_types.h>
- /* This struct defines a memory VMM memory area. */
- struct vm_area_struct {
- struct mm_struct * vm_mm; /* VM area parameters */
- unsigned long vm_start;
- unsigned long vm_end;
- /* linked list of VM areas per task, sorted by address */
- struct vm_area_struct *vm_next;
- pgprot_t vm_page_prot;
- unsigned long vm_flags;
- /* AVL tree of VM areas per task, sorted by address */
- short vm_avl_height;
- struct vm_area_struct * vm_avl_left;
- struct vm_area_struct * vm_avl_right;
- /* For areas with an address space and backing store,
- vm_area_struct *vm_next_share;
- struct vm_area_struct **vm_pprev_share;
- struct vm_operations_struct * vm_ops;
- unsigned long vm_pgoff; /* offset in PAGE_SIZE units, *not* PAGE_CACHE_SIZE */
- struct file * vm_file;
- unsigned long vm_raend;
- void * vm_private_data; /* was vm_pte (shared mem) */
- };
假如该vm_area_struct描述的是一个文件映射的虚存空间,成员vm_file便指向被映射的文件的file结构,vm_pgoff是该虚存空间起始地址在vm_file文件里面的文件偏移,单位为物理页面。
图3.2
因此,mmap系统调用所完成的工作就是准备这样一段虚存空间,并建立vm_area_struct结构体,将其传给具体的设备驱动程序.
2.
linux有2个方法建立页表:
(1)
返回值:
成功返回
参数说明:
vma
virt_addr
pfn
size
prot
(2)
返回值:
成功则返回一个有效映射页,失败返回NULL.
参数说明:
address
返回一个有效映射页.
(3)
remap_pfn_range不能映射常规内存,只存取保留页和在物理内存顶之上的物理地址。因为保留页和在物理内存顶之上的物理地址内存管理系统的各个子模块管理不到。640
3.
(4)
- Linux内存管理之mmap详解 (2
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- Linux内存管理之mmap详解
- 小空间大精彩!Apple Watch重磅实战案例之QQ空间
- jqgrid+bootstrap样式实践
- 到底该如何学习数据结构?
- 对这些高薪的诱惑,你要长点心!
- 《从零开始学Swift》学习笔记(Day 23)——尾随闭包
- Linux内存管理之mmap详解
- python __init__.py
- ArcGIS Runtime加载本地Shape数据和编辑Shape数据
- cocos2d-x之3.8音频管理
- 我们为什么需要动效设计
- 搭建SSH环境笔记(一)
- netlink通信机制分析
- Java transient Volatile关键字
- Android应用原码编译大致过程概括