• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >Android > mmap实现分析

mmap实现分析

作者:网友 字体:[增加 减小] 来源:互联网 时间:2017-05-26

网友通过本文主要向大家介绍了mmap文件阅读器下载,mmap文件阅读器,mmap,mmap文件怎么打开,mmap思维导图软件等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

mmap实现分析


mmap实现分析

本文不是介绍mmap函数的使用方法,而是分析其内核实现,相关使用方法网上已经有很多资料。Mmap的本质其实就是:为当前进程分配(或找到)一个合适的vma,然后为该vma设置对应的缺页处理函数。

我们知道mmap按照flag可以分为匿名映射和非匿名映射,又可分为shared映射和private映射。这样从两个维度,我们就得到了四种映射。

(1)匿名shared映射:fd为-1,可用于父子进程通信。

(2)匿名private映射:例如malloc大块的内存(大于128k)。

(3)非匿名shared映射:常见的用于进程通信方式。

(4)非匿名private映射:例如程序在启动时加载so时,就是用的这种方式,相当于“写时拷贝”。

下面我们就看下内核中几种方式的区别。

内核中mmap主要有函数sys_mmap_pgoff函数负责实现,该函数定义在mm/mmap.c中。

  1. SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
  2. unsigned long, prot, unsigned long, flags,
  3. unsigned long, fd, unsigned long, pgoff)
  4. {
  5. struct file *file = NULL;
  6. unsigned long retval = -EBADF;
  7. if (!(flags & MAP_ANONYMOUS)) { /*匿名映射*/
  8. audit_mmap_fd(fd, flags);
  9. if (unlikely(flags & MAP_HUGETLB))
  10. return -EINVAL;
  11. file = fget(fd); /*由fd找到对应的file结构*/
  12. if (!file)
  13. goto out;
  14. if (is_file_hugepages(file))
  15. len = ALIGN(len, huge_page_size(hstate_file(file)));
  16. } else if (flags & MAP_HUGETLB) {
  17. /*......*/
  18. }
  19. flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
  20. retval = vm_mmap_pgoff(file, addr, len, prot, flags, pgoff);
  21. if (file)
  22. fput(file);
  23. out:
  24. return retval;
  25. }

该函数主要功能由vm_mmap_pgoff来实现,而vm_mmap_pgoff主要逻辑就是调用了do_mmap_pgoff。下面我们看vm_mmap_pgoff的实现。

ldo_mmap_pgoff

  1. unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
  2. unsigned long len, unsigned long prot,
  3. unsigned long flags, unsigned long pgoff,
  4. unsigned long *populate)
  5. {
  6. struct mm_struct * mm = current->mm;
  7. struct inode *inode;
  8. /*......*/
  9. /* Obtain the address to map to. we verify (or select) it and ensure
  10. * that it represents a valid section of the address space.
  11. */
  12. addr = get_unmapped_area(file, addr, len, pgoff, flags);
  13. if (addr & ~PAGE_MASK)
  14. return addr;
  15. /*......*/
  16. addr = mmap_region(file, addr, len, vm_flags, pgoff);
  17. /*......*/
  18. return addr;
  19. }

这个函数首先通过 get_unmapped_area创建(或获取)一个合适的vma,然后调用mmap_region对vma进行设置。我们具体看下mmap_region的实现。

lmmap_region

  1. unsigned long mmap_region(struct file *file, unsigned long addr,
  2. unsigned long len, vm_flags_t vm_flags, unsigned long pgoff)
  3. {
  4. struct mm_struct *mm = current->mm;
  5. struct vm_area_struct *vma, *prev;
  6. int correct_wcount = 0;
  7. int error;
  8. struct rb_node **rb_link, *rb_parent;
  9. unsigned long charged = 0;
  10. struct inode *inode = file ? file_inode(file) : NULL;
  11. /*......*/
  12. if (file) { /*如果不是匿名映射*/
  13. if (vm_flags & (VM_GROWSDOWN|VM_GROWSUP))
  14. goto free_vma;
  15. if (vm_flags & VM_DENYWRITE) {
  16. error = deny_write_access(file);
  17. if (error)
  18. goto free_vma;
  19. correct_wcount = 1;
  20. }
  21. vma->vm_file = get_file(file);
  22. error = file->f_op->mmap(file, vma); /*调用对应文件系统的mmap函数*/
  23. if (error)
  24. goto unmap_and_free_vma;
  25. addr = vma->vm_start;
  26. pgoff = vma->vm_pgoff;
  27. vm_flags = vma->vm_flags;
  28. } else if (vm_flags & VM_SHARED) { /*shared 匿名映射*/
  29. if (unlikely(vm_flags & (VM_GROWSDOWN|VM_GROWSUP)))
  30. goto free_vma;
  31. error = shmem_zero_setup(vma);
  32. if (error)
  33. goto free_vma;
  34. } /*private 匿名映射*/
  35. file = vma->vm_file;
  36. /*......*/
  37. }

如果传入了fd,则调用对应文件系统的mmap函数。以ext4文件系统为例。其mmap函数为 ext4_file_mmap。

lext4_file_mmap

  1. static int ext4_file_mmap(struct file *file, struct vm_area_struct *vma)
  2. {
  3. struct address_space *mapping = file->f_mapping;
  4. if (!mapping->a_ops->readpage)
  5. return -ENOEXEC;
  6. file_accessed(file);
  7. vma->vm_ops = &ext4_file_vm_ops;
  8. return 0;
  9. }

可以看到这个函数只是设置vma->vm_ops为当前文件系统的处理函数。

  1. static const struct vm_operations_struct ext4_file_vm_ops = {
  2. .fault = filemap_fault,
  3. .page_mkwrite = ext4_page_mkwrite,
  4. .remap_pages = generic_file_remap_pages,
  5. };

如果是匿名映射(不传入fd),且传入了shared flag。则调用shmem_zero_setup。

lshmem_zero_setup

  1. int shmem_zero_setup(struct vm_area_struct *vma)
  2. {
  3. struct file *file;
  4. loff_t size = vma->vm_end - vma->vm_start;
  5. file = shmem_file_setup("dev/zero", size, vma->vm_flags);
  6. if (IS_ERR(file))
  7. return PTR_ERR(file);
  8. if (vma->vm_file)
  9. fput(vma->vm_file);
  10. vma->vm_file = file;
  11. vma->vm_ops = &shmem_vm_ops;
  12. return 0;
  13. }

可以看到这里将vma->vm_ops设置为tmpfs文件系统的shmem_vm_ops。

  1. static const struct vm_operations_struct shmem_vm_ops = {
  2. .fault = shmem_fault,
  3. #ifdef CONFIG_NUMA
  4. .set_policy = shmem_set_policy,
  5. .get_policy = shmem_get_policy,
  6. #endif
  7. .remap_pages = generic_file_remap_pages,
  8. };

整个mmap函数的处理过程如下:

我们知道mmap函数只是为进程分配了虚拟内存空间,并没有真的建立虚拟内存和物理内存的映射。这个建立映射的过程是到缺页中断的函数中进行的。

缺页中断的处理过程大体如下:

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • mmap实现分析

相关文章

  • 2017-05-26安卓OKhttp请求封装,安卓okhttp封装
  • 2017-05-26ViewHolder模式超简洁写法,viewholder模式写法
  • 2017-05-26Android蓝牙技术Bluetooth初体验
  • 2017-05-26MVP解析,mvp模式解析实践
  • 2017-05-26Android实战技巧之四十八:Android上的Java8和kotlin
  • 2017-05-26Android:支持多选的本地相册
  • 2017-05-26onTouch和onTouchEvent,ontouch
  • 2017-05-26Android面试题(2),android面试题
  • 2017-05-26Android WebView File域同源策略绕过漏洞浅析
  • 2017-05-26Android SDK在线更新镜像服务器,androidsdk

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • msm8909+android5.1.1--打开调试(debug)串口
    • Android View的绘制流程,androidview绘制
    • Android 如何保证service在后台不被kill,androidkill
    • MaterialRefreshLayout,swiperefreshlayout
    • 更多,更多大片访问
    • dpdk内存管理——内存初始化
    • 状态栏一体化及其带来的软键盘自适应问题
    • Android中MotionEvent的来源和ViewRootImpl
    • 高通QCOM 8610平台电量计算
    • android 编程小技巧(持续中)

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有