欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  科技

brk() 和 mmap() 内存映射

程序员文章站 2022-04-11 15:34:39
参考博文:http://www.cnblogs.com/huxiao-tee/p/4660352.html x86平台下linux进程虚拟地址空间分布(2.6.7以前版本) mmap区域与栈区域相对增长,只有1GB连续的虚拟地址空间可用。 x86平台下linux进程虚拟地址空间分布(2.6.7以后版 ......

参考博文:http://www.cnblogs.com/huxiao-tee/p/4660352.html

  • x86平台下linux进程虚拟地址空间分布(2.6.7以前版本)
  • brk() 和 mmap() 内存映射

    mmap区域与栈区域相对增长,只有1GB连续的虚拟地址空间可用。

  • x86平台下linux进程虚拟地址空间分布(2.6.7以后版本)

brk() 和 mmap() 内存映射

Random stack offset:由于之前栈的地址是固定的,容易被人利用栈溢出进行攻击,这里栈每次有一个偏移量。

RLIMIT_STACK:向栈中压入数据容量超过栈的容量时,会触发page fault,异常会检测到最近的虚拟地址空间,发现产生异常的地址与栈相邻,会扩大栈的大小(一般是8M)。如果栈被加长,栈针回退时不会再收缩,如果stack overflow则会导致segment fault。

Memory Mapping Segment:内存映射的位置,一种高效I/O,后面会细说。

  • 对heap的操作函数  brk() 和 sbrk()  

      int brk(void *addr);

    void sbrk(intptr_t increment);

    内核数据结构mm_struct中 start_brk是进程动态分配的起始地址(heap的起始地址),brk 是堆当前最后的地址。      

    首先program break就是当前brk的位置,所以他是数据段初始化结束后heap的第一个位置,而不是heap的尾部。

    sbrk()是库函数,brk()是系统调用,相对于库函数来说一般系统调用会提供相对简单的工作。都是改变brk的值来扩展收缩堆(increment 为负数时收缩)。

  • mmap 映射区函数

   1.基础概念

    mmap 是一种内存映射方法,将一个文件或其他对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址一一对应的关系。内核空间对这块区域的改变也直接反应到用户空间,实现不同进程的文件共享。

    linux内核使用vm_area_struct结构表示一个独立的虚拟内存区域,一个进程使用多个vm_area_struct来分别表示不同类型的虚拟内存区域.

    当vm_area_struct数目较少时,按照升序以单恋表的形式组织结构,在数目较多时使用AVL树来实现。

brk() 和 mmap() 内存映射v

mmap函数是创建一个新的vm_area_struct结构,并将其与物理地址相连

   2.  mmap内存映射原理

    分为三个阶段

    • 进程启动映射过程,并在虚拟地址空间中为映射创建虚拟映射区域  

       1>进程在用户空间调用mmap。

       原型:void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);

       2>在当前进程的虚拟地址空间中,寻找一段空间满足要求的连续的虚拟地址。

       3>为此虚拟区分配一个vm_area_struct 结构,接着对这个结构的各个域进行初始化

       4>将新建的虚拟结构(vm_area_struct)插入到进程的虚拟地址区的链表或数种。

    • 调用内核空间的系统调用函数mmap(不同于用户空间)实现文件物理地址和进程虚拟地址的一一映射关系 

       5>为映射分配了新的虚拟地址区域后,通过待映射的文件指针,在文件描述符表中找到对应的文件描述符,加入到struct file中 

       6>linux中的file_operation结构中定义了不同事件对应的设备驱动函数,其中有  int mmap(struct file *filp, struct vm_area_struct *vma),其实这个函数就是将用户空间与设备内存相连,也就是对虚拟地址的访问转化为对设备的访问

       7>通过inode模块找到对应的文件,也就是磁盘的物理地址

       8>建立页表,实现文件地址和虚拟地址区域的映射关系。这里只建立了映射关系,主存中没有对应物理地址的数据。

    • 进程发起对这片映射空间的访问,引发缺页异常,实现文件内容到主存的拷贝

       9>进程的读写,通过查询页表发现这一段地址不再物理页面上,引发缺页异常

       10>进行缺页异常判断,申请调页

       11>先判断swap cache中没有没需要访问的内存页,如果没有调用nopage把所缺德页从磁盘装入主存

       12>之后可以进行读写,会有一段时间延迟,调用msync()立即更新。

   3. mmap优点总结

         1>对文件的读取操作跨过了页缓存,减少了数据的拷贝次数,使用内存读取代了I/O操作,提高了文件读取效率。

    2>实现了用户空间和内核空间的高效交互方式

    3>提供进程间共享内存及相互通信方式

    4>实现高效的大规模数据传输

 

还有内核的高端内存映射:https://www.cnblogs.com/wuchanming/p/4360277.html