Android Ashmem相关介绍

基本原理

Android 的Ashmem是一种共享内存的机制,它基于mmap系统调用,不同进程可以将同一段物理内存映射到各自的虚拟地址控制,从而实现共享。

 

Ashmem与mmap的区别

mmap通过映射同一个普通文件实现进程间共享内存,普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read,write等操作。进程在映射空间对共享内存的改变并不直接写回到磁盘文件中,在调用munmap后才执行此操作。可以通过调用msync实现磁盘上文件内存与共享内存区的内容一致。

Ashmem与mmap的区别在于Ashmem与cache shrinker关联起来,可以控制cache shrinker在适当时机回收这些共享内存。

 

Ashmem的实现

Ashmem的源代码在mm/ashmem.c中,它通过注册Cache Shrinker回收内存,通过注册misc设备提供open,mmap等接口,mmap则通过tmpfs创建文件来分配内存,tmpfs将一块内存虚拟为一个文件,这样操作共享内存就相当于操作一个文件。

Ashmem用两个结构体ashmem_area和ashmem_range来维护分配的内存,ashmem_area代表共享的内存区域,ashmem_range则将这段区域以页为单位分为多个range。

ashmem_area有个unpinned_list成员,挂在这个list上的range可以被回收。ashmem_range有一个LRU链表,在cache shrink回收一个ashmem_area的某段内存时候,是根据LRU的原则来选择哪些页面优先被回收的。

Ashmem的基本结构如下图所示。

 

下面依次简单分析主要函数功能:

l ashmem_init

这是module初始化函数,Ashmem是作为一个模块实现的。该函数主要功能:

n 调用kmem_cache_create分别创建struct ashmem_area和structashmem_range 的slab cache

n 调用misc_register注册 ahsmem driver

n 调用register_shrinker注册Ashmem的 CacheShrinker

l ashmem_open

标准misc设备的open函数。它调用kmem_cache_zalloc分配一个 ashmem_area,并初始化各成员变量。

l ashmem_release

做与ashmem_open相反工作,释放tmpfs文件,ashmem_area及其ashmem_range。

l ashmem_mmap

mmap操作,主要就是调用shmem_file_setup从tmpfs文件系统中创建一个文件(实际上就是一段RAM)给ashmem_area用,该文件代表着这段被共享的内存。Ashmem真正实现进程共享内存的机制是靠shmem这个linux标准机制提供的。

l ashmem_shrink

即Ashmem的cacheshrink函数。它被mm/vmscan.c::shrink_slab调用,或者被用户的 ioctl

命令调用。这个函数从LRU链表上回收指定数目的 unpinned ashmem_range。

l ashmem_ioctl

这个函数提供ioctl 接口,它实现了如下命令:

 

l ashmem_unpin

unpin一段内存。实现的方法很简单,就是分配一个ashmem_range,把它挂到ashmem_area -> unpinned_list上,并加到 LRU链表上。

ashmem_pin

pin一段内存,从 ashmem_area->unpinned_list上拿下这个 ashmem_range,由此可知,被unpin的range才能被回收,pin的range则不能回收。

 

用户接口

Ashmem驱动创建了/dev/ashmem设备文件,进程A可通过open打开该文件,用ioctl命令ASHMEM_SET_NAME和ASHMEM_SET_SIZE设置共享内存块的名字和大小,并将得到的handle传给mmap,来获得共享的内存区域,进程B通过将相同的handle传给mmap,获得同一块内存,handle在进程间的传递可通过Binder来实现。


你可能感兴趣的:(android,cache,list,struct,Module,磁盘)