Android 匿名共享内存基础数据结构篇(二)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hello_java_Android/article/details/88101047
Android匿名共享内存系统架构
Android匿名共享内存系统架构图

如上图所示,Android系统匿名共享内存(以下以Ashmem代替)以Ashmem驱动为基础,在运行时库提供了cutils library来对Ashmem驱动进行访问,同时又在Framework层提供了C++和Java类接口来访问cutils。

    这篇文章主要学习kernel层ashmem的基础数据结构,先来看看Ashmem到底是什么!源码版本Android 5

    Ashmem驱动程序主要由ashmem.c和ashmem.h来实现,ashmem.h文件目录:kernel/include/uapi/linux/ashmem.h,ashmem.c文件目录:kernel/drivers/staging/android/ashmem.c,Ashmem驱动程序主要使用了三个结构体:ashmem_area, ashmem_range, ashmem_pin,前两个结构体定义在ashmem.c文件中,ashmem_pin定义在ashmem.h文件中:

结构体ashmem_area用来描述一块Ashmem---->
 

42 /**
 43  * struct ashmem_area - The anonymous shared memory area
 44  * @name:       The optional name in /proc/pid/maps 
 45  * @unpinned_list:  The list of all ashmem areas
 46  * @file:       The shmem-based backing file
 47  * @size:       The size of the mapping, in bytes
 48  * @prot_masks:     The allowed protection bits, as vm_flags
 49  *
 50  * The lifecycle of this structure is from our parent file's open() until
 51  * its release(). It is also protected by 'ashmem_mutex'
 52  *
 53  * Warning: Mappings do NOT pin this structure; It dies on close()
 54  */
 55 struct ashmem_area {
 56     char name[ASHMEM_FULL_NAME_LEN]; /* optional name in /proc/pid/maps */
 57     struct list_head unpinned_list;  /* list of all ashmem areas */
 58     struct file *file;       /* the shmem-based backing file */
 59     size_t size;             /* size of the mapping, in bytes */
 60     unsigned long vm_start;      /* Start address of vm_area
 61                       * which maps this ashmem */
 62     unsigned long prot_mask;     /* allowed prot bits, as vm_flags */
 63 };

name字段解释:

结构体ashmem_area用来描述一块匿名共享内存区域,name用来保存匿名共享内存名称,同时会被写入到文件/proc/<pid>/maps中,<pid>表示创建该Ashmem的进程PID,ASHMEM_FULL_NAME_LEN表示name的长度,定义在文件头部:

38 #define ASHMEM_NAME_PREFIX "dev/ashmem/"
 39 #define ASHMEM_NAME_PREFIX_LEN (sizeof(ASHMEM_NAME_PREFIX) - 1)
 40 #define ASHMEM_FULL_NAME_LEN (ASHMEM_NAME_LEN + ASHMEM_NAME_PREFIX_LEN)

每一块Ashmem名称都是以dev/ashmem/为前缀,如果调用者未指定名称则:#define ASHMEM_NAME_DEF     "dev/ashmem"为其默认名称,如果指定了名称长度限制为:#define ASHMEM_NAME_LEN     256  这两个定义在头文件ashmem.h中。

unpinned_list字段:

该字段用来描述一个解锁内存块列表,一块Ashmem可以被划分为多个小块,当这些小块内存处于解锁状态时,他们会被添加到所属匿名共享内存的解锁内存列表中,主要是为内存管理服务。

file、size字段:

匿名共享内存是基于linux系统的临时文件系统tmpfs来实现的,因此每一块匿名共享内存在临时文件系统tmpfs中都有一个对应的文件,这个文件大小即为匿名共享内存大小即size字段。

vm_start字段:

创建完匿名共享内存临时文件后需要将其映射到进程的地址空间,该字段表示将Ashmem临时文件映射到进程地址空间的起始位置。

prot_mask字段:

描述一块Ashmem的访问保护位,定义如下:ashmem.c

 #define PROT_MASK       (PROT_EXEC | PROT_READ | PROT_WRITE)

结构体ashmem_range用来描述一块处于解锁状态的内存---->

65 /**
 66  * struct ashmem_range - A range of unpinned/evictable pages
 67  * @lru:             The entry in the LRU list
 68  * @unpinned:            The entry in its area's unpinned list
 69  * @asma:            The associated anonymous shared memory area.
 70  * @pgstart:             The starting page (inclusive)
 71  * @pgend:           The ending page (inclusive)
 72  * @purged:          The purge status (ASHMEM_NOT or ASHMEM_WAS_PURGED)
 73  *
 74  * The lifecycle of this structure is from unpin to pin.
 75  * It is protected by 'ashmem_mutex'
 76  */
 77 struct ashmem_range {
 78     struct list_head lru;
 79     struct list_head unpinned;
 80     struct ashmem_area *asma;
 81     size_t pgstart;
 82     size_t pgend;
 83     unsigned int purged;
 84 };

处于解锁状态的小块内存都是从一块匿名共享内存中划分出来的,他们通过unpinned成员变量链入宿主匿名共享内存的解锁内存列表unpinned_list中。一块处于解锁状态的内存宿主匿名共享内存是通过成员变量asma来描述的。

在Ashmem中,每一块处于解锁状态的内存都会通过成员变量lru链入到一个全局列表ashmem_lru_list中,这是个最近最少使用列表,定义如下:

/* LRU list of unpinned pages, protected by ashmem_mutex */
  static LIST_HEAD(ashmem_lru_list);

处于解锁状态的内存都是目前不在需要使用的内存块,当系统内存不足的时候内存管理系统就会按照规则回收ashmem_lru_list中的内存块,成员变量pgstart和pgend用来描述这块处于解锁状态的内存块的起始地址和结束地址,单位是page(页)。

成员变量purged用来描述一块处于解锁状态的内存块是否已经被回收,他的值定义在头文件ashmem.h中:

12 /* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
 13 #define ASHMEM_NOT_PURGED   0     未被回收
 14 #define ASHMEM_WAS_PURGED   1     已被回收

结构体ashmem_pin用来描述一块即将被锁定或者解锁的内存--->
 

 20 struct ashmem_pin {
 21     __u32 offset;   /* offset into region, in bytes, page-aligned */
 22     __u32 len;  /* length forward from offset, in bytes, page-aligned */
 23 };

offset表示描述的这块内存在其宿主匿名共享内存中的偏移值,len表示要被锁定或者解锁的内存块的大小,以字节为单位,并且对齐到页面边界的。

这三个结构体共同描述了一块Ashmem的多个状态,ashmem_area结构体即一块匿名共享内存的本体,即 告诉我们这块内存到底是什么。结构体ashmem_range描述Ashmem的解锁状态记录,提供内存管理相关便利。而ashmem_pin主要是一小块内存在被锁定或者解锁的过程中使用。

猜你喜欢

转载自blog.csdn.net/hello_java_Android/article/details/88101047