Android中mmap原理及应用简析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android中mmap原理及应用简析相关的知识,希望对你有一定的参考价值。

参考技术A

mmap是Linux中常用的系统调用API,用途广泛,android中也有不少地方用到,比如匿名共享内存,Binder机制等。本文简单记录下Android中mmap调用流程及原理。mmap函数原型如下:

几个重要参数

返回值是void *类型,分配成功后,被映射成虚拟内存地址。

mmap属于系统调用,用户控件间接通过swi指令触发软中断,进入内核态(各种环境的切换),进入内核态之后,便可以调用内核函数进行处理。 mmap->mmap64->__mmap2->sys_mmap2-> sys_mmap_pgoff ->do_mmap_pgoff

而 __NR_mmap在系统函数调用表中对应的减值如下:

通过系统调用,执行swi软中断,进入内核态,最终映射到call.S中的内核函数:sys_mmap2

sys_mmap2最终通过sys_mmap_pgoff在内核态完成后续逻辑。

sys_mmap_pgoff通过宏定义实现

进而调用do_mmap_pgoff:

get_unmapped_area用于为用户空间找一块内存区域,

current->mm->get_unmapped_area一般被赋值为arch_get_unmapped_area_topdown,

先找到合适的虚拟内存(用户空间),几经周转后,调用相应文件或者设备驱动中的mmap函数,完成该设备文件的mmap,至于如何处理处理虚拟空间,要看每个文件的自己的操作了。

这里有个很关键的结构体

它是文件驱动操作的入口,在open的时候,完成file_operations的绑定,open流程跟mmap类似

先通过get_unused_fd_flags获取个未使用的fd,再通过do_file_open完成file结构体的创建及初始化,最后通过fd_install完成fd与file的绑定。

重点看下path_openat:

拿Binder设备文件为例子,在注册该设备驱动的时候,对应的file_operations已经注册好了,

open的时候,只需要根根inode节点,获取到file_operations既可,并且,在open成功后,要回调file_operations中的open函数

open后,就可以利用fd找到file,之后利用file中的file_operations *f_op调用相应驱动函数,接着看mmap。

Binder机制中mmap的最大特点是一次拷贝即可完成进程间通信 。Android应用在进程启动之初会创建一个单例的ProcessState对象,其构造函数执行时会同时完成binder mmap,为进程分配一块内存,专门用于Binder通信,如下。

第一个参数是分配地址,为0意味着让系统自动分配,流程跟之前分子类似,先在用户空间找到一块合适的虚拟内存,之后,在内核空间也找到一块合适的虚拟内存,修改两个控件的页表,使得两者映射到同一块物力内存。

Linux的内存分用户空间跟内核空间,同时页表有也分两类,用户空间页表跟内核空间页表,每个进程有一个用户空间页表,但是系统只有一个内核空间页表。而Binder mmap的关键是:也更新用户空间对应的页表的同时也同步映射内核页表,让两个页表都指向同一块地址,这样一来,数据只需要从A进程的用户空间,直接拷贝拷贝到B所对应的内核空间,而B多对应的内核空间在B进程的用户空间也有相应的映射,这样就无需从内核拷贝到用户空间了。

binder_update_page_range完成了内存分配、页表修改等关键操作:

可以看到,binder一次拷贝的关键是,完成内存的时候,同时完成了内核空间跟用户空间的映射,也就是说,同一份物理内存,既可以在用户空间,用虚拟地址访问,也可以在内核空间用虚拟地址访问。

普通文件的访问方式有两种:第一种是通过read/write系统调访问,先在用户空间分配一段buffer,然后,进入内核,将内容从磁盘读取到内核缓冲,最后,拷贝到用户进程空间,至少牵扯到两次数据拷贝;同时,多个进程同时访问一个文件,每个进程都有一个副本,存在资源浪费的问题。

另一种是通过mmap来访问文件,mmap()将文件直接映射到用户空间,文件在mmap的时候,内存并未真正分配,只有在第一次读取/写入的时候才会触发,这个时候,会引发缺页中断,在处理缺页中断的时候,完成内存也分配,同时也完成文件数据的拷贝。并且,修改用户空间对应的页表,完成到物理内存到用户空间的映射,这种方式只存在一次数据拷贝,效率更高。同时多进程间通过mmap共享文件数据的时候,仅需要一块物理内存就够了。

共享内存是在普通文件mmap的基础上实现的,其实就是基于tmpfs文件系统的普通mmap,有机会再分析,不再啰嗦。

Android中mmap原理及应用简析

仅供参考,欢迎指正

Android 之LocalBroadcastManager原理简析

LocalBroadcastManager原理简析

1、BroadcastReceiver的缺点

Android的广播应用的很广泛,其根本原理就是观察者模式的应用,在Android开发应用中观察者模式的应用是很广泛的,比如EventBus组件,RecycleViewListView等都是利用了观察者模式。但是相较于BroadcastReceiver来说,有如下缺点:
1、

以上是关于Android中mmap原理及应用简析的主要内容,如果未能解决你的问题,请参考以下文章

Android之ViewStub源码简析

Android之ViewStub源码简析

Android中同步屏障的应用及简析

Android 之LocalBroadcastManager原理简析

Android 之LocalBroadcastManager原理简析

Kafka架构及基本原理简析