ashmem 的意思就是 Anonymous Shared Memory ,即匿名共享内存。 Android 系统主要包括五个部分,分别是 Linux 内核、本地库、 Dalvik 虚拟机、应用程序框架和应用程序。对于其中的 Linux 内核部分,最初 Android 是基于 2.6.25 的,而且 Android 内核基本是同 Linux 内核同步更新的, Android Linux 内核的基础上做了一些修改和功能上的添加。目前最新的开源版本是 Android2.3 ,它是基于 Linux-2.6.35 的,它于 2010 12 7 日公布。

其中 Android Linux 内核的功能上的添加,就有 ashmem ,它为进程提供大块共享内存,同时为内核提供回收和管理这个内存的机制,其源代码位于 Android 源码中的 kernel/mm/ashmem.c 中:( Android 内核版本 2.0 Eclair ),它是基于 2.6.29

1 、用到的数据结构:

(1)struct ashmem_area Android 共享内存区,当父文件(应该也可以理解成父进程)调用 open() 函数时有效,至它调用 release() 函数消亡,通过“ ashmem_mutex ”来保护其互斥性。具体定义如下:

  1. struct ashmem_area{
  2. char name[ASHMEM_NAME_LEN];
  3. struct list_headunpinned_list;
  4. struct file*file;
  5. size_t size;
  6. unsignedlong prot_mask;
  7. };
struct ashmem_area { char name[ASHMEM_NAME_LEN]; struct list_head unpinned_list; struct file *file; size_t size; unsigned long prot_mask; }; char name[ASHMEM_NAME_LEN]; /* 申请的一块 ashmem 的名称 */

struct list_head unpinned_list; /* ashmem 区的链表,用来把所有区连接起来 */

struct file *file; /* 支持 shmem-based 的文件, struct file 结构体定义 */

size_t size; /* 内存映射的大小,以 bytes 为单位 */

unsigned long prot_mask; /* 一个类似于标志位的变量 */

(2)struct ashmem_range :代表 unpinned evictable )页的区间,生命周期从 unpin pin ,同样由“ ashmem_mutex ”来保证其互斥性。

  1. struct ashmem_range{
  2. struct list_headlru;
  3. struct list_headunpinned;
  4. struct ashmem_area*asma;
  5. size_t pgstart;
  6. size_t pgend;
  7. unsignedint purged;
  8. };
struct ashmem_range { struct list_head lru; struct list_head unpinned; struct ashmem_area *asma; size_t pgstart; size_t pgend; unsigned int purged; }; struct list_head lru; /* LRU (最近最少使用)链表 */

struct list_head unpinned; /* unpinned 区域链表 */

struct ashmem_area *asma; /* 相关的 ashmem 区域 */

size_t pgstart; /* 页开始位置(包含在页内) */

size_t pgend; /* 页结束位置(包含在页内) */

unsigned int purged; /* 标志变量, ASHMEM_NOT ASHMEM_WAS_PURGED */

定义的几个全局变量:

  1. static LIST_HEAD(ashmem_lru_list);
static LIST_HEAD(ashmem_lru_list); /* LRU 链表的定义 */

  1. static unsigned long lru_count;

static unsigned long lru_count; / * LRU 链表计数器 */

  1. static DEFINE_MUTEX(ashmem_mutex);

static DEFINE_MUTEX(ashmem_mutex); /* 用来保证互斥性的 ashmem_mutex 初始化 */

  1. static struct kmem_cache*ashmem_area_cachep__read_mostly;/

static struct kmem_cache *ashmem_area_cachep __read_mostly; / * 指向 ashmem_area 的指针变量 */

  1. static struct kmem_cache*ashmem_range_cachep__read_mostly;

static struct kmem_cache *ashmem_range_cachep __read_mostly; /* 指向 ashmem_range 的指针变量 */

宏定义实现的函数:

  1. #definerange_size(range)((range)->pgend-(range)->pgstart+1)

#define range_size(range) ((range)->pgend - (range)->pgstart + 1) /* 用来返回 unpinned 页的 size */

  1. #definerange_on_lru(range)((range)->purged==ASHMEM_NOT_PURGED)

#define range_on_lru(range) ((range)->purged == ASHMEM_NOT_PURGED) /* 修改标志 purged 的值为 ASHMEM_NOT_PURGED ,表示这段内存没有清空 */

  1. #definepage_range_subsumes_range(range,start,end)(((range)->pgstart>=(start))&&((range)->pgend<=(end)))

#define page_range_subsumes_range(range, start, end) (((range)->pgstart >= (start)) && ((range)->pgend <= (end))) /* 判断是否在页内,参数为 range 结构体、起始地址、结束地址 */

  1. #definepage_range_subsumed_by_range(range,start,end)(((range)->pgstart<=(start))&&((range)->pgend>=(end)))

#define page_range_subsumed_by_range(range, start, end) (((range)->pgstart <= (start)) && ((range)->pgend >= (end))) /* 判断是否在页外 */

  1. #definepage_in_range(range,page)(((range)->pgstart<=(page))&&((range)->pgend>=(page)))

#define page_in_range(range, page) (((range)->pgstart <= (page)) && ((range)->pgend >= (page))) /* 判断是否在页内,参数为 range 结构体、页号 */

  1. #definepage_range_in_range(range,start,end)(page_in_range(range,start)||page_in_range(range,end)||page_range_subsumes_range(range,start,end))

#define page_range_in_range(range, start, end) (page_in_range(range, start) || page_in_range(range, end) || page_range_subsumes_range(range, start, end)) /* 判断是否在页内参数为 range 结构体、起始地址、结束地址 */

  1. #definerange_before_page(range,page)((range)->pgend<(page))

#define range_before_page(range, page) ((range)->pgend < (page)) /* 判断 rangge 结构体定义的页时候在 page 之前 */

4 、函数实现:

(1) 内联函数:

  1. static inline void lru_add( struct ashmem_range*range)

static inline void lru_add(struct ashmem_range *range) /* LRU 链表进行添加结点 */

  1. static inline void lru_del( struct ashmem_range*range)

static inline void lru_del(struct ashmem_range *range) /* LRU 链表进行删除结点 */

  1. static inline void range_shrink( struct ashmem_range*range, size_t start, size_t end)

static inline void range_shrink(struct ashmem_range *range, size_t start, size_t end) /* 修改 range 结构体定义的内存的大小,可以进行缩短 */

基本函数:

  1. static int range_alloc( struct ashmem_area*asma, struct ashmem_range*prev_range,
  2. unsignedint purged, size_t start, size_t end)

static int range_alloc(struct ashmem_area *asma, struct ashmem_range *prev_range, unsigned int purged, size_t start, size_t end) /* 初始化一个ashmem_area结构体 */

  1. static void range_del( struct ashmem_range*range)

static void range_del(struct ashmem_range *range) /* 删除一个ashmem_area,就是从链表中删除 */

static struct file_operations ashmem_fops 成员函数:

  1. struct file_operations定义如下:
  2. static struct file_operationsashmem_fops={
  3. .owner=THIS_MODULE,
  4. .open=ashmem_open,
  5. .release=ashmem_release,
  6. .mmap=ashmem_mmap,
  7. .unlocked_ioctl=ashmem_ioctl,
  8. .compat_ioctl=ashmem_ioctl,
  9. };

struct file_operations定义如下: static struct file_operations ashmem_fops = { .owner = THIS_MODULE, .open = ashmem_open, .release = ashmem_release, .mmap = ashmem_mmap, .unlocked_ioctl = ashmem_ioctl, .compat_ioctl = ashmem_ioctl, };

成员函数定义如下:

  1. static int ashmem_open( struct inode*inode, struct file*file)

static int ashmem_open(struct inode *inode, struct file *file) /* 创建一个文件对象,也就是为一个 ashmem_area 结构体申请一段空间 */

  1. static int ashmem_release( struct inode*ignored, struct file*file)

static int ashmem_release(struct inode *ignored, struct file *file) /* 释放文件对象,也就是释放 ashmem_area 结构体 */

  1. static int ashmem_mmap( struct file*file, struct vm_area_struct*vma)

static int ashmem_mmap(struct file *file, struct vm_area_struct *vma) /* 将制定的文件映射到制定的进程区域中 */

  1. static long ashmem_ioctl( struct file*file,unsigned int cmd,unsigned long arg)

static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) 说明:函数实现如下:

  1. static long ashmem_ioctl( struct file*file,unsigned int cmd,unsigned long arg)
  2. {
  3. struct ashmem_area*asma=file->private_data;
  4. long ret=-ENOTTY;
  5. switch (cmd){
  6. case ASHMEM_SET_NAME:
  7. ret=set_name(asma,(void __user*)arg);
  8. break ;
  9. case ASHMEM_GET_NAME:
  10. ret=get_name(asma,(void __user*)arg);
  11. break ;
  12. case ASHMEM_SET_SIZE:
  13. ret=-EINVAL;
  14. if (!asma->file&&!(arg&~PAGE_MASK)){
  15. ret=0;
  16. asma->size=(size_t )arg;
  17. }
  18. break ;
  19. case ASHMEM_GET_SIZE:
  20. ret=asma->size;
  21. break ;
  22. case ASHMEM_SET_PROT_MASK:
  23. ret=set_prot_mask(asma,arg);
  24. break ;
  25. case ASHMEM_GET_PROT_MASK:
  26. ret=asma->prot_mask;
  27. break ;
  28. case ASHMEM_PIN:
  29. case ASHMEM_UNPIN:
  30. case ASHMEM_GET_PIN_STATUS:
  31. ret=ashmem_pin_unpin(asma,cmd,(void __user*)arg);
  32. break ;
  33. case ASHMEM_PURGE_ALL_CACHES:
  34. ret=-EPERM;
  35. if (capable(CAP_SYS_ADMIN)){
  36. ret=ashmem_shrink(0,GFP_KERNEL);
  37. ashmem_shrink(ret,GFP_KERNEL);
  38. }
  39. break ;
  40. }
  41. return ret;
  42. }

static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { struct ashmem_area *asma = file->private_data; long ret = -ENOTTY; switch (cmd) { case ASHMEM_SET_NAME: ret = set_name(asma, (void __user *) arg); break; case ASHMEM_GET_NAME: ret = get_name(asma, (void __user *) arg); break; case ASHMEM_SET_SIZE: ret = -EINVAL; if (!asma->file && !(arg & ~PAGE_MASK)) { ret = 0; asma->size = (size_t) arg; } break; case ASHMEM_GET_SIZE: ret = asma->size; break; case ASHMEM_SET_PROT_MASK: ret = set_prot_mask(asma, arg); break; case ASHMEM_GET_PROT_MASK: ret = asma->prot_mask; break; case ASHMEM_PIN: case ASHMEM_UNPIN: case ASHMEM_GET_PIN_STATUS: ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg); break; case ASHMEM_PURGE_ALL_CACHES: ret = -EPERM; if (capable(CAP_SYS_ADMIN)) { ret = ashmem_shrink(0, GFP_KERNEL); ashmem_shrink(ret, GFP_KERNEL); } break; } return ret; } 其中 ashmem_ioctl 函数可以实现的功能有:

ASHMEM_SET_NAME 设置名称,调用 set_name 函数。

ASHMEM_GET_NAME 获取名称,调用 get_name 函数。

ASHMEM_SET_SIZE 设置 ashmem 的大小,通过改变 ashmem_area 中的成员变量设置。

ASHMEM_GET_SIZE 获得 ashmem 的大小,通过读 ashmem_area 的成员变量获取。

ASHMEM_SET_PROT_MASK 设置 prot_mask ,调用 set_prot_mask 函数。

ASHMEM_GET_PROT_MASK 获取 prot_mask ,通过读 ashmem_area 的成员变量获取。

ASHMEM_PIN 使用 pin 语法,调用 ashmem_pin_upin 函数,通过判断再调用 ashmem_pin 函数。

ASHMEM_UNPIN 使用 upin 语法,调用 ashmem_pin_upin 函数,通过判断再调用 ashmem_upin 函数。

ASHMEM_GET_PIN_STATUS 获取 pin 状态,调用 ashmem_pin_upin 函数,通过判断再调用 ashmem_get_pin_status 函数。

⑩ASHMEM_PURGE_ALL_CACHES " 净化 " 所有 cache ,调用 ashmem_shrink 函数。

(4) 模块函数:定义模块的入口函数和出口函数。

static int __init ashmem_init (void)

/* 模块编程的规范,入口函数 */

static void __exit ashmem_exit (void)

/* 模块编程的规范,出口函数 */

原文地址: http://blog.csdn.net/wzyhb123456789/archive/2010/12/27/6101192.aspx

更多相关文章

  1. C语言函数以及函数的使用
  2. android自定义属性的使用
  3. Android 内核简单分析

随机推荐

  1. sdcard
  2. 浅入浅出 Android 安全:第二章 Android Li
  3. 如何把多个Android Project打包成一个APK
  4. Android九环刀之RatingBar之评委请亮分
  5. Android应用程序防止被LMK干掉
  6. 升级Android SDK后ADT找不到adb.exe文件
  7. Android Debug Bridge(adb, Android调试
  8. Android视频播放程序关键部分简要解析
  9. Android API Demos学习(1) - Hello World
  10. Android中Bundle的使用示例