欢迎访问南京建策科技股份有限公司! 分支机构: 南京 | 广州 | 上海 | 扬州 | 常州
 最新动态 NEWS     More...
【喜报】再来一波,恭喜以下1...
【喜报】恭喜以下建策学员顺利...
【喜报】抓住2019的尾巴,...
纸短情长|因为你的肯定温暖着...
有人@你:您收到一封表扬信
又是全过,恭喜小伙伴们通过H...

 

  网站位置:首页 > 学习交流 > 技术文档下载
vmalloc与mmap
[2019-4-26]

mmap()系统调用是在用户进程与内核之间共享内存区域的常用方法。我们最近有个程序,需要应用进程能够读取内核驱动获取的数据,经过简单的调研,决定采用mmap方式。实现起来不难,在驱动中注册一个字符设备,实现该设备的mmap()方法即可。但这其中有一点小曲折。


在实现设备的mmap()方法时,需要将物理内存映射到应用程序通过mmap()系统调用传下来的vma中。vma代表的是进程的一段虚拟地址空间。在第一版里,考虑的不全面,利用alloc_pages()将整个内存段申请为一段连续的物理地址空间。然后通过remap_pfn_range()函数将这段连续的物理内存映射到vma中。经过长时间的测试,没有发现问题。直到今天,在部署一个老集群时,遇到了问题。这个集群中有很多老机器,内存只有十多个G,而且长时间运行后产生了大量的内存碎片。从而导致,我们无法获得足够的连续物理内存。没办法,只好重新调整驱动中分配内存的方式,改用vmalloc获取地址空间。


在kernel里,通常有3种申请内存的方式:vmalloc, kmalloc, alloc_pages。kmalloc与alloc_pages类似,均是申请连续的地址空间。而vmalloc则可以申请一段不连续的物理地址空间,并将其映射到连续的线性地址上。每次vmalloc之后,内核会创建一vm_struct,用以映射分配到的不连续的内存区域。vm_struct类似vma,但是又不是一回事。vma是将物理内存映射到进程的虚拟地址空间。而vm_struct是将物理内存映射到内核的线性地址空间。  


既然vmalloc拿到的不是连续的物理内存,那么将这些内存映射到vma时,就不能直接利用remap_pfn_range()了。


此时可以采用两种方法,一种是实现vm_operations_struct的fault()方法,用以在缺页时再映射需要的页。此方法操作起来较为麻烦。


另一种方法是直接使用remap_vmalloc_range()函数。该函数的原型为:



其中参数vma是mmap使用调用传下来的,addr即为vmalloc()所分配内存的起始地址。而pgoff则为mmap()系统调用里的偏移参数,可以通过vma->vm_pgoff获得。该函数成功执行后,返回值为0。如果返回值为负数,则说明出错了。通常是由于所传的参数不正确。


需要注意的是,需要映射到用户空间的内存段,不能直接利用vmalloc()分配,而应该使用vmalloc_user()函数。该函数除了分配内存之外,还会将相应的vm_struct结构标记为VM_USERMAP。否则,remap_vmalloc_range将返回错误。


在这个项目中碰到的教训是,永远不要假设系统中一定会有超过一个页的连续物理内存。


不过较新的内核具有compact机制,可以整理内存碎片。但是,目前至少有一大部分机器不支持,或未开启此机制。


如果您对技术帖内容有任何疑问,请联系官方邮箱:jcit@jiancenj.com,也欢迎广大学员踊跃投稿,一经录用,有稿费酬谢

友情链接
 
腾讯云
华三
红帽
思科
瞻博网络
 Copyright @ 2016-2019 www.jiancenj.com All Rights Reserved. 版权所有 建策科技 苏ICP备11058165号
 总 部地 址:江苏省南京市玄武区珠江路222号长发科技大厦16楼 联系电话: 025-84804339;84804652
 广州办事处:广州市天河区石牌西路8号展望数码广场1903室
 上海办事处:上海普陀区真南路1008号上海信息技术学院8号楼114室
 常州办事处:常州市武进区科教城创研港3A804 18796950509
 扬州办事处:扬州市邗江区润扬南路33号南京邮电大学通达学院2号实验楼2203-2206室