Mmap 实现原理和应用(流程)

在调试完达芬奇的视屏输入后记录一下调试心得。重点还是再次放在系统调用mmap后的内存分配上。做了一个mmap系统调用的笔记以及记录以备后用。大致介绍了linux中对于mmap的应用以及后续产生缺页异常处理的一个流程。

由于之前的调试中一直对于vma的区域选取产生疑问,不知道vma到底是何许人也,这次有机会就直接mmap调试了。一下内容都通过log信息验证。

 

系统调用 mmap后

SYSCALL_DEFINE6(mmap_pgoff,unsigned long, addr, unsigned long, len,

                  unsignedlong, prot, unsigned long, flags,

                  unsignedlong, fd, unsigned long, pgoff)

| - >

unsigned long do_mmap_pgoff(structfile *file, unsigned long addr,

                                                                                                unsignedlong len, unsigned long prot,

                                                                                                unsignedlong flags, unsigned long pgoff)

| - >

unsigned long mmap_region(struct file*file, unsigned long addr,

                                                                                              unsignedlong len, unsigned long flags,

                                                                                     unsignedint vm_flags, unsigned long pgoff)

 

 

         通过mmap_region最后调用驱动中填写的mmap函数,

static struct v4l2_file_operations omap34xxcam_fops = {

         .owner                    = THIS_MODULE,

         .unlocked_ioctl     = video_ioctl2,

         .poll                         =omap34xxcam_poll,

         .mmap                    = omap34xxcam_mmap,

         .open                      = omap34xxcam_open,

         .release                  = omap34xxcam_release,

};

 

         mmap函数最终是要解决什么?解决物理以及虚拟内存的分配,和对应关系。在函数mmap_region在vm_area_cachep 中分配一个vma。

         vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL);

 

这个vma就是将来在驱动中使用的空间。既然是空间,那么有起点和终点。起点就是addr,终点就是addr+len。

vma->vm_start = addr;

         vma->vm_end = addr + len;

 

         关于这个addr的确定查看函数:get_unmapped_area(file, addr, len, pgoff,flags);

         这个地址范围落在用户空间 0G-3G [ 0x 0000 0000 – 0xC000 0000]。

 

        

 

 

现在有了vma,有了地址以及空间那么怎么落实最后的内存上,这是在函数

static int __kprobes

do_page_fault(unsigned long addr, unsigned int fsr, structpt_regs *regs)中完成。

| ->

static int __kprobes

__do_page_fault(structmm_struct *mm, unsigned long addr, unsigned int fsr,

                                                                                                                  structtask_struct *tsk)

        

         在函数__do_page_fault中直接使用要访问的虚拟地址作为参数在mm_struct中去寻找相应的vma。这个vma就是系统调用mmap中分配以及初始化的。现在真的要用到vma的起始地址了。但是mmap系统调用中没有把vma所描述的内存区域和物理内存联系起来。所谓联系就是建立相关的页表及页表项。当程序真正去访问一个已经存在但是没有建立物理内存的地址时,缺页异常发生。

         __do_page_fault函数中vma = find_vma(mm,addr);找到包含有该地址的vma。然后调用handle_mm_fault以及handle_pte_fault分配建立页表。最终当缺页异常处理完成后,以上mmap中申请的内存区域就变得有效并且可以访问了。

         在这两个建立页表的函数中遇到了一些page到物理地址以及虚拟地址的转换。在另外一片文章中介绍。

 

谢谢。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值