Android内核源码阅读---ashmem.c

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

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

1 、用到的数据结构:

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

  1. struct  ashmem_area {  
  2.     char  name[ASHMEM_NAME_LEN];  
  3.     struct  list_head unpinned_list;  
  4.     struct  file *file;  
  5.     size_t  size;  
  6.     unsigned long  prot_mask;  
  7. };  
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 :代表 unpinnedevictable )页的区间,生命周期从 unpinpin ,同样由“ ashmem_mutex ”来保证其互斥性。

  1. struct  ashmem_range {  
  2.     struct  list_head lru;  
  3.     struct  list_head unpinned;  
  4.     struct  ashmem_area *asma;  
  5.     size_t  pgstart;  
  6.     size_t  pgend;  
  7.     unsigned int  purged;  
  8. };  
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_NOTASHMEM_WAS_PURGED */

定义的几个全局变量:

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

  1. static  unsigned  long  lru_count;  

/ * LRU 链表计数器 */

  1. static  DEFINE_MUTEX(ashmem_mutex);  

/* 用来保证互斥性的 ashmem_mutex 初始化 */

  1. static   struct  kmem_cache *ashmem_area_cachep __read_mostly; /  

* 指向 ashmem_area 的指针变量 */

  1. static   struct  kmem_cache *ashmem_range_cachep __read_mostly;  

/* 指向 ashmem_range 的指针变量 */

宏定义实现的函数:

  1. #define range_size(range)  ((range)->pgend - (range)->pgstart + 1)   

/* 用来返回 unpinned 页的 size */

  1. #define range_on_lru(range)  ((range)->purged == ASHMEM_NOT_PURGED)   

/* 修改标志 purged 的值为 ASHMEM_NOT_PURGED ,表示这段内存没有清空 */

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

/* 判断是否在页内,参数为 range 结构体、起始地址、结束地址 */

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

/* 判断是否在页外 */

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

/* 判断是否在页内,参数为 range 结构体、页号 */

  1. #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. #define range_before_page(range, page)  ((range)->pgend < (page))   

/* 判断 rangge 结构体定义的页时候在 page 之前 */

4 、函数实现:

(1) 内联函数:

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

/* LRU 链表进行添加结点 */

  1. 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)  

/* 修改 range 结构体定义的内存的大小,可以进行缩短 */

基本函数:

 

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

/* 初始化一个ashmem_area结构体 */

  1. static   void  range_del( struct  ashmem_range *range)  

/* 删除一个ashmem_area,就是从链表中删除 */

static struct file_operations ashmem_fops 成员函数:

  1. struct  file_operations定义如下:  
  2. static   struct  file_operations ashmem_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. };  

成员函数定义如下:

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

/* 创建一个文件对象,也就是为一个 ashmem_area 结构体申请一段空间 */

  1. 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)  

/* 将制定的文件映射到制定的进程区域中 */

  1. 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. }  

其中 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值