转自:http://blog.sina.com.cn/s/blog_606334a20100goei.html

更详细的讲解请看:http://blog.csdn.net/luoshengyang/article/details/6664554


ashmem是android的内存分配/共享机制,在dev目录下对应的设备是/dev/ashmem,相比于传统的内存分配机制,如malloc、anonymous/named mmap,其好处是提供了辅助内核内存回收算法的pin/unpin机制。


ashmme的典型用法是先打开设备文件,然后做mmap映射。

第一步通过调用ashmem_create_region函数,这个函数完成这几件事:

1)fd = open("/dev/ashmem", O_RDWR);
2)ioctl(fd, ASHMEM_SET_NAME, region_name); // 这一步可选
3)ioctl(fd, ASHMEM_SET_SIZE, region_size);

第二步,应用程序一般会调用mmap来把ashmem分配的空间映射到进程空间:

mapAddr = mmap(NULL, pHdr->mapLength, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);

应用程序还可以通过ioctl来pin和unpin某一段映射的空间,以提示内核的pagecache算法可以把哪些页面回收,这是一般mmap做不到的。

可以说ashmem以较小的代价(用户需进行额外的ioctl调用来设置名字,大小,pin和unpin),获得了一些内存使用的智能性。

ashmem本身实现也很小巧,只有不到700行。原因是借助了内核已经有的工具,例如shmem_file_setup(支撑文件),cache_shrinker(slab分配算法的页面回收的回调函数)等。

如果ashmem不使用内核驱动实现,则pin/unpin的语义比较难以实现,或者即使实现,效率也不会很高。但查询android源码,使用pin/unpin很少,看来ashmem还是没有很好地用起来。

如果不使用ashmem驱动,并且舍弃pin/unpin语义,那么模拟ashmem的语义还是很简单的。首 先,ashmem_create_region可以为进程创建一个唯一的文件(如进程名+时戳),打开,然后返回这个文件的fd;接着应用程序可以进性一 般的mmap操作了。如果不使用ashmem_create_region接口函数,那么使用anonymous的mmap就可以了,但这种方式属于正在 被丢弃的方式,而且并不是所有的系统都支持,比如Macos就不支持。


Androidashmem语义的实现

ashmem非常象是anonymous mmap,这或许是它的名字的由来吧。网上有人问pin和unpin到底是做什么用的,似乎没人回答。简单的回答是:没什么用。深沉点的回答是:可以用来更有效地使用内存。具体讲,当你觉得用ashmem分配的空间有部分似乎不大用得着时,你可以unpin这一块空间,unpin后,内核可以把它对应的物理页面回收,挪作他用。你并不用担心以后进程对unpin的空间的访问,因为回收了的内存,你还可以再次获得(通过缺页handler),因为unpin操作并不改变已经mmap的地址空间。所以说,pin/unpin纯粹是内核内部的操作,不影响上层应用的语义。

如果不用ashmem驱动,不考虑pin/unpin语义,并且考虑到现有API的持续性(ashmem_create_region等),实现ashmem的语义虽然概念上不难,但还是有一些细节需要注意。

首先,ashmem不是用于进程间共享数据的,这是由驱动实现决定的。驱动把ashmem分配的地址空间赋给file结构的private,这就排除了进程间共享的可能性。

其次,ashmem的作用等同于anonymous mmap,纯粹作分配空间用,你打开多少次/dev/ashmem设备(并mmap),你就获得多少次(不同的)空间。这在同一个进程也是一样的。这一点很重要。

举例来说:
fd1 = open("/dev/ashmem", O_RDWR);
addr1 = mmap(0, size, ..., fd1, ...);
fd2 = open("/dev/ashmem", O_RDWR);
addr2 = mmap(0, size, ..., fd2, ...);

即使在同一个进程内,addr1和addr2也是不同的。用/dev/zero达不到这个效果,普通文件也不行。

所以,在使用普通文件模拟ashmem行为时,必须给每个文件起唯一的名字。这个技术可有很多选择,比如使用开机后经历的时间作为文件名的一部分。

更多相关文章

  1. 一款霸榜 GitHub 的开源 Linux 资源监视器!
  2. Android跨进程通信IPC之4——关于"JNI"的那些事
  3. android usb流程(加整理)
  4. android Binder 工作流程
  5. Android监控程序本身被卸载方法汇总
  6. 一些资料,binder,content provider
  7. android之init进程-uevent
  8. android如何打印当前的线程及进程
  9. Android(安卓)framework系统默认设置修改

随机推荐

  1. 解决The'InnoDB'feature is disa
  2. mysql常识以及存储引擎,锁和事务
  3. 05-mysql中的查询(第一章)
  4. Active Record或mysql中的批次计数
  5. Innode表空间碎片优化
  6. Win2003+IIS6.0+PHP+MYSQL+ASP+ASP.NET全
  7. VS2015 使用Mysql-connector/c++ 链接数
  8. mysql数据库监控利器lepus天兔工具安装和
  9. Mysql主从复制读写分离
  10. MySQL查询返回用户的收件人列表