0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

mmap系统调用和vmalloc获取地址空间

Linux阅码场 来源:工程师曾玲 2019-02-02 16:13 次阅读

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机制,可以整理内存碎片。但是,目前至少有一大部分机器不支持,或未开启此机制。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    3

    文章

    1357

    浏览量

    40179
  • 内存
    +关注

    关注

    8

    文章

    2959

    浏览量

    73792
  • malloc
    +关注

    关注

    0

    文章

    52

    浏览量

    62

原文标题:vmalloc与mmap

文章出处:【微信号:LinuxDev,微信公众号:Linux阅码场】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    linux内核系统调用之参数传递

    与普通函数一样,系统调用通常需要一些输入/输出参数,这些参数可能包括实际值(即数字)、用户模式进程地址空间中的变量地址,甚至包括指向用户模式
    的头像 发表于 12-20 09:32 1323次阅读

    拆解mmap内存映射的本质!

    mmap 内存映射里所谓的内存其实指的是虚拟内存,在调用 mmap 进行匿名映射的时候(比如进行堆内存的分配),是将进程虚拟内存空间中的某一段虚拟内存区域与物理内存中的匿名内存页进行映
    的头像 发表于 01-24 14:30 1316次阅读
    拆解<b class='flag-5'>mmap</b>内存映射的本质!

    Linux的mmap文件内存映射机制

    一。mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问
    发表于 03-08 09:54

    字符设备驱动另一种写法—mmap方法操作LED

    。经过自己的研究之后,我发现还有另外一种写法,直接在应用层操作,省去了内核中的地址映射部分,使得用户可以在应用层直接操作LED。 mmap方法是把设备物理地址直接映射到用户空间的一种
    发表于 01-02 17:38

    Linux用户空间与内核空间的区别?

    对于提供了MMU(存储管理器,辅助操作系统进行内存管理,提供虚实地址转换等硬件支持)的处理器而言,Linux提供了复杂的存储管理系统,使得进程所能访问的内存达到4GB。进程的4GB内存空间
    发表于 06-05 04:35

    labview 中怎么获取数值的指针(地址)?调用dll时要往里面传地址

    labview 中怎么获取数值的指针(地址)?调试一个设备,调用dll时要往里面传地址,看了官方.h文件,参考了官方的C#代码,自己用labview试了试,老是不对,所以想先
    发表于 03-15 08:59

    linux drivers中的mmap实现

    将设备驱动内核空间的内存映射到用户空间里,可以通过用户空间中的mmap系统调用代替
    发表于 05-15 10:31 1587次阅读

    Linux的mmap文件内存映射机制

    IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。  mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程
    发表于 04-02 14:35 420次阅读

    如何主动调用获取flag

    明明有强大的frida工具,可以无需过反调试,无需IDA去动静态调试,无需获取RC4密钥,直接用主动调用获取flag,何必走繁琐的路呢?
    的头像 发表于 10-10 09:44 4039次阅读
    如何主动<b class='flag-5'>调用</b><b class='flag-5'>获取</b>flag

    PCI总线地址空间系统地址空间的关系

    于PCI总线统一寻址。每个PCI设备通过PCI寄存器中的基地址寄存器来指定映射的首地址。PCI地址空间对应于计算机系统结构中的PCI总线。
    的头像 发表于 01-06 08:30 2225次阅读

    内核mmap_sem锁的危害和相关优化

    mmap_sem锁是进程为了保护自身虚拟地址空间不受多线程并发访问影响而设计的。
    的头像 发表于 02-07 16:01 665次阅读

    Linux内核之物理内存组织结构

    虚拟内存区域使用起始地址和结束地址描述,链表按起始地址递增排序。两系统调用区别:mmap指定的偏
    的头像 发表于 02-08 09:47 906次阅读

    Linux应用开发之共享内存

    mmap() 系统调用调用进程的虚拟地址空间中创建一个新的内存映射,映射分为两种。
    的头像 发表于 04-06 09:51 392次阅读

    Linux虚拟地址空间和物理地址空间的关系

    过程,这其实也是MMU的工作原理。 我们知道,在Linux中,每个进程都有自己独立的地址空间,且互不干扰。每个进程的地址空间又分为用户空间
    的头像 发表于 10-08 11:40 1067次阅读
    Linux虚拟<b class='flag-5'>地址</b><b class='flag-5'>空间</b>和物理<b class='flag-5'>地址</b><b class='flag-5'>空间</b>的关系

    mmap原理详解

    一句话概括mmap mmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。 这样,进程不仅能像访问内存一样读写文件,多个进程映射
    的头像 发表于 11-09 14:59 643次阅读
    <b class='flag-5'>mmap</b>原理详解