Android核心分析之二十五Android GDI之共享缓冲区机制
Androird GDI之共享缓冲区机制
  1  native_handle_t对private_handle_t 的包裹     private_handle_t是gralloc.so使用的本地缓冲区私有的数据结构,而Native_handle_t是上层抽象的可以在进程间传递的数据结构。在客户端是如何还原所传递的数据结构呢?首先看看native_handle_t对private_handle_t的抽象包装。
                      
  numFds= sNumFds=1;
  numInts= sNumInts=8;
  这个是Parcel中描述句柄的抽象模式。实际上是指的Native_handle所指向句柄对象的具体内容:
  numFds=1表示有一个文件句柄:fd/
  numInts= 8表示后面跟了8个INT型的数据:magic,flags,size,offset,base,lockState,writeOwner,pid;
  由于在上层系统不要关心buffer_handle_t中data的具体内容。在进程间传递buffer_handle_t(native_handle_t)句柄是其实是将这个句柄内容传递到Client端。在客户端通过Binder读取readNativeHandle @Parcel.cpp新生成一个native_handle。
  native_handle* Parcel::readNativeHandle() const
  {
  …
  native_handle* h = native_handle_create(numFds, numInts);
  for (int i=0 ; err==NO_ERROR && idata = dup(readFileDescriptor());
  if (h->data < 0) err = BAD_VALUE;
  }
  err = read(h->data + numFds, sizeof(int)*numInts);
  …。
  return h;
  }
  这里需要提到的是为在构造客户端的native_handle时,对于对方传递过来的文件句柄的处理。由于不是在同一个进程中,所以需要dup(…)一下为客户端使用。这样就将Native_handle句柄中的,客户端感兴趣的从服务端复制过来。这样就将Private_native_t的数据:magic,flags,size,offset,base,lockState,writeOwner,pid;复制到了客户端。
  客户端利用这个新的Native_buffer被Mapper传回到gralloc.xxx.so中,获取到native_handle关联的共享缓冲区映射地址,从而获取到了该缓冲区的控制权,达到了客服端和Server间的内存共享。从SurfaceFlinger来看就是作图区域的共享。
  2 Graphic Mapper是干什么的?    服务端(SurfaceFlinger)分配了一段内存作为Surface的作图缓冲,客户端怎样在这个作图缓冲区上工作呢?这个就是Mapper(GraphicBufferMapper)y要干的事情。两个进程间如何共享内存,如何获取到共享内存?Mapper就是干这个得。需要利用到两个信息:共享缓冲区设备句柄,分配时的偏移量。Mapper利用这样的原理:
  客户端只有lock,unlock,实质上就是mmap和ummap的操作。对于同样一个共享缓冲区,偏移量才是总要的,起始地址不重要。实际上他们操作了同一物理地址的内存块。我们在上面讨论了native_handle_t对private_handle_t 的包裹过程,从中知道服务端给客户端传递了什么东西。
  进程1在共享内存设备上预分配了8M的内存。以后所有的分配都是在这个8M的空间进行。对以该文件设备来讲,8M物理内存提交后,就实实在在的占用了8M内存。每个每个进程都可以同个该内存设备共享该8M的内存,他们使用的工具就会mmap。由于在mmap都是用0开始获取映射地址,所以所有的客户端进程都是有了同一个物理其实地址,所以此时偏移量和size就可以标识一段内存。而这个偏移量和size是个数值,从服务进程传递到客户端直接就可以使用。
                     
  3 GraphicBuffer(缓冲区代理对象)
  typedef struct android_native_buffer_t
  {
  struct android_native_base_t common;
  int width;
  int height;
  int stride;
  int format;
  int usage;
  …
  buffer_handle_t handle;
  …
  } android_native_buffer_t;
  关系图表:
  GraphicBuffer :EGLNativeBase :android_native_buffer_t
  GraphicBuffer(parcel &)建立本地的GraphicBuffer的数据native_buffer_t。在通过接收对方的传递的native_buffer_t 构建GraphicBuffer。我们来看看在客户端Surface::lock获取操作缓冲区的函数调用:
  Surface::lock(SurfaceInfo* other, Region* dirtyIn, bool blocking)
  {int Surface::dequeueBuffer(android_native_buffer_t** buffer)(Surface)
  {status_t Surface::getBufferLocked(int index, int usage)
  {
  sp buffer = s->requestBuffer(index, usage);
  {
  virtual sp requestBuffer(int bufferIdx, int usage)
  {   remote()->transact(REQUEST_BUFFER, data, &reply);
  sp buffer = new GraphicBuffer(reply);
  Surface::Lock建立一个在Client端建立了一个新的GraphicBuffer 对象,该对象通过(1)描述的原理将SurfaceFlinger的buffer_handle_t相关数据构成新的客户端buffer_handle_t数据。在客户端的Surface对象就可以使用GraphicMapper对客户端buffer_handle_t进行mmap从而获取到共享缓冲区的开始地址了。
  4 总结
  Android在该节使用了共享内存的方式来管理与显示相关的缓冲区,他设计成了两层,上层是缓冲区管理的代理机构GraphicBuffer,及其相关的native_buffer_t,下层是具体的缓冲区的分配管理及其缓冲区本身。上层的对象是可以在经常间通过Binder传递的,而在进程间并不是传递缓冲区本身,而是使用mmap来获取指向共同物理内存的映射地址。
Android核心分析之二十五Android GDI之共享缓冲区机制的更多相关文章
- Android核心分析之二十四Android GDI之显示缓冲管理
		Android GDI之屏幕设备管理-动态链接库 万丈高楼从地起,从最根源的硬件帧缓冲区开始.我们知道显示FrameBuffer在系统中就是一段内存,GDI的工作就是把需要输出的内容放入到该段内存的某 ... 
- Android核心分析之二十八Android GDI之Surface&Canvas
		Surface&Canvas Canvas为在画布的意思.Android上层的作图几乎都通过Canvas实例来完成,其实Canvas更多是一种接口的包装.drawPaints ,drawPoi ... 
- Android核心分析之二十六Android GDI之SurfaceFlinger
		Android GDI之SurfaceFlinger SurfaceFinger按英文翻译过来就是Surface投递者.SufaceFlinger的构成并不是太复杂,复杂的是他的客户端建构.Sufac ... 
- Android核心分析之二十二Android应用框架之Activity
		3 Activity设计框架 3.1 外特性空间的Activity 我们先来看看,android应用开发人员接触的外特性空间中的Activity,对于AMS来讲,这个Activity就是客服端的 ... 
- Android核心分析之二十Android应用程序框架之无边界设计意图
		Android应用程序框架1 无边界设计理念 Android的应用框架的外特性空间的描述在SDK文档(http://androidappdocs.appspot.com/guide/topics/fu ... 
- Android核心分析之二十一Android应用框架之AndroidApplication
		Android Application Android提供给开发程序员的概念空间中Application只是一个松散的表征概念,没有多少实质上的表征.在Android实际空间中看不到实际意义上的应用程 ... 
- Android项目实战(二十五):Android studio 混淆+打包+验证是否成功
		前言: 单挑Android项目,最近即时通讯用到环信,集成sdk的时候 官方有一句 在 ProGuard 文件中加入以下 keep. -keep class com.hyphenate.** {*;} ... 
- Android Studio 使用教程(二十五)之运行Android Studio工程
		一.Android虚拟设备入口 上期我们使用了Android Studio创建了HeloWorld工程,要想运行该工程,首先需要一个Android虚拟设备来模拟Android程序的运行. 重新打开An ... 
- Android核心分析之二十三Andoird GDI之基本原理及其总体框架
		Android GDI基本框架 在Android中所涉及的概念和代码最多,最繁杂的就是GDI相关的代码了.但是本质从抽象上来讲,这么多的代码和框架就干了一件事情:对显示缓冲区的操作和管理. GDI主 ... 
随机推荐
- oracle增加表空间的四种方法,查询表空间使用情况
			增加表空间大小的四种方法Meathod1:给表空间增加数据文件ALTER TABLESPACE app_data ADD DATAFILE'D:\ORACLE\PRODUCT\10.2.0\ORADA ... 
- C++设计模式——工厂方法模式
			本文版权归果冻说所有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留追究法律责任的权利.» 本文链接:http://www.jellythink.com/arch ... 
- VBS基础篇 - 内置函数
			Date/Time 函数 函数 描述 CDate 把有效的日期和时间表达式转换为日期(Date)类型. Date 返回当前的系统日期. DateAdd 返回已添加指定时间间隔的日期. DateDiff ... 
- C++(MFC)编程中遇到的的一些函数
			memset void memset( void dest, int c, size_t count ); dest: Pointer to destination c: Character to s ... 
- C#开源系统大汇总(转)
			一.AOP框架 Encase 是C#编写开发的为.NET平台提供的AOP框架.Encase 独特的提供了把方面(aspects)部署到运行时代码,而其它AOP框架依赖配置文件的方式.这种 ... 
- android开发,设置listview的高度无效
			一般是在item的layout中设置高度 android:layout_height="100dp" 但是发现这样后无效,因此找到解决办法,如下: android:minHeigh ... 
- Byte measurements
- 用PHP对数据库数据进行删除
			显示页面: <body> <table width="100%" border="1" cellpadding="0" c ... 
- 关于Office 2013的几个问题
			最近在阅读一些pdf的材料,想对其中做一些批注,但是PDF文档做批准比较麻烦,而且市场上的几个pdfToWord也不是很好用. 偶然的机会发现,使用office2013可以直接打开pdf文件,所以赶紧 ... 
- 【BZOJ】【2565】最长双回文串
			Manacher算法 找出一个最长子串S=X+Y,且X和Y都是回文串,求最长的长度是多少…… 同时找两个串明显很难搞啊……但是我们可以先找到所有的回文串!在找回文串的同时我们可以预处理出来l[i]和r ... 
