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()函数。该函数的原型为:

int remap_vmalloc_range(struct vm_area_struct *vma, void *addr,
unsigned long pgoff)

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

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

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

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

vmalloc与mmap相关推荐

  1. linux精华文章汇总

    这里总结下linux相关的一些技术文章,涉及内存,进程,驱动,调试调优等方面,为了方便读者的查阅,后续会持续更新. linux 内存管理 告别"一页障目" Linux的内存初始化 ...

  2. Linux - 内存管理

    引用文章 Linux阅马场 初探Linux内核态--通过proc文件系统作快速问题定位 linux通过meminfo 与 slab 定位内存泄漏 曾文斌: /proc/meminfo之谜完全揭秘 vm ...

  3. Linux内存管理基础

    系统启动之Linux内存管理基础 Keywords 非一致内存访问(NUMA)模型.节点(node).内存管理区(Zone).一致内存访问(UMA)模型.内核页表.内存管理区分配器(伙伴系统Buddy ...

  4. kmalloc,vmalloc,malloc,mmap

    kmalloc cat /proc/slabinfo kmalloc也是基于slab机制,按照2^order创建对个slab描述符.在系统启动时通过函数 create_kmalloc_caches进行 ...

  5. 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )

    文章目录 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) 二.内存管理流程 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) " 堆内存 " ...

  6. ioremap 与 mmap【转】

    转自:http://blog.csdn.net/junllee/article/details/7415732 内存映射 对于提供了MMU(存储管理器,辅助操作系统进行内存管理,提供虚实地址转换等硬件 ...

  7. 内存映射MMAP和DMA【转】

    转自:http://blog.csdn.net/zhoudengqing/article/details/41654293 版权声明:本文为博主原创文章,未经博主允许不得转载. 这一章介绍Linux内 ...

  8. Linux内存管理和分析vmalloc使用的地址范围

    From: http://www.cnblogs.com/dubingsky/archive/2010/04/20/1716158.html Vmalloc可以获得的地址在VMALLOC_START到 ...

  9. 内核空间:kmalloc vmalloc 用户空间:malloc ptmalloc

    一.地址映射流程  二.内核空间 在内核空间,通过malloc类似的两个系统调用来进行内存的分配,它们分别是kmalloc和vmalloc 1.kmalloc kmalloc用于为内核空间的直接内存映 ...

  10. linux mmap 函数详解,Linux之mmap函数简介

    本文主要讲述mmap 函数的使用,与驱动中 mmap 函数的实现 mmap 怎么使用,怎么实现,为什么 mmap 可以减少额外的拷贝? 下面简单详情. 一. mmap 的使用#include void ...

最新文章

  1. SAP Classification(物料特性)
  2. Android应用与系统安全防御
  3. 项目移植,项目环境问题
  4. 一款简约多类PHP导航源码
  5. __attribute__((visibility()))
  6. 将xml转为txt_HZ文章转短视频工具v1.0 快速将文章转为短视频 自动配音 配字幕 配图...
  7. Razor语法(三)
  8. JavaScript事件---事件入门
  9. 基础集合论笔记 目录
  10. 《英语语法新思维 基础版1》读书笔记(二)
  11. 能上QQ不能上浏览器处理方法(win11版)
  12. 腾讯云轻量应用服务器免费升级2核4G8M升级4核4G8M不花钱
  13. Gitter---高颜值GitHub小程序客户端诞生记,2021年安卓社招面试题精选
  14. 查询失败,后台服务器运行错误,添加网络打印机错误?怎么处理?Windows 无法连接到打印机。 服务器打印后台处理程序服务没有运行。...
  15. ios11修改微信步数_你会时常去看他的微信步数吗?
  16. python之路--生成器
  17. IDEA代码以及注释格式化,行宽设置,以及自动换行
  18. 非期望产出的sbm模型_兼顾非期望产出的工业用地效率测度、分异与溯因 ——以东北三省为例...
  19. 解决win10系统下Elasticsearch闪退问题
  20. 蓝牙怎么区分单模和双模_蓝牙中的单模、双模是什么,它们有何不同

热门文章

  1. CSS篇 Process Document第7章 Technical Report Development Process翻译
  2. 中国银行外币汇率查询
  3. 迪杰斯特拉算法c语言实现
  4. vue程序中组件间的传值方式
  5. 【python】从web抓取信息
  6. 快速学习nodejs系列:四、nodejs特性1--单线程
  7. 医疗保健行业未来发展的5大趋势预测
  8. 总结之:CentOS 6.5 rsync+inotify实现数据实时同步备份
  9. 利用EEPROM实现arduino的断电存储
  10. linux系统删除openjdk并安装oracle jdk