Binder学习笔记(五)—— Parcel是怎么打包数据的?
前文中曾经遇到过Parcel,从命名上知道他负责数据打包。在checkService的请求/响应体系中,Parcel只打包了基本数据类型,如Int32、String16……后面还要用于打包抽象数据类型flat_binder_object,这会稍微复杂一些,因此有必要拿出来单独研究。我们从Parcel::writeInterfaceToken(…)追起,它的层层调用关系如下,这些函数都在frameworks/native/libs/binder/Parcel.cpp文件中,行数和函数名为:
writeInterfaceToken(…)
Parcel::writeInt32(int32_t val)
Parcel::writeAligned(val)
所有的基本数据类型的打包最后都由writeAligned(…)实现的,其内部逻辑也非常简单,
frameworks/native/libs/binder/Parcel.cpp:1149
template<class T>
status_t Parcel::writeAligned(T val) {
COMPILE_TIME_ASSERT_FUNCTION_SCOPE(PAD_SIZE_UNSAFE(sizeof(T)) == sizeof(T)); if ((mDataPos+sizeof(val)) <= mDataCapacity) {
restart_write:
*reinterpret_cast<T*>(mData+mDataPos) = val; // 将val追加到mData
return finishWrite(sizeof(val));
} status_t err = growData(sizeof(val)); // 如果mData空间不够,则先扩容
if (err == NO_ERROR) goto restart_write;
return err;
}
mData是一块内存栈,writeXXX则把数据写入栈,如果mData空间不够,先给mData扩容,并把原先的数据搬到新的空间,再把新数据写入栈。
Parcel::writeStrongBinder(…)的逻辑更复杂一些,它的调用关系如下:
frameworks/native/libs/binder/Parcel.cpp
Parcel::writeStrongBinder(const sp<IBinder>& val)
Parcel::flatten_binder(const sp<ProcessState>& /*proc*/, const sp<IBinder>& binder =val, Parcel* out=this)
来看flatten_binder(…),frameworks/native/libs/binder/Parcel.cpp:205
status_t flatten_binder(const sp<ProcessState>& /*proc*/,
const sp<IBinder>& binder, Parcel* out)
{
flat_binder_object obj; obj.flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
if (binder != NULL) {
IBinder *local = binder->localBinder();
if (!local) { // remote类型的binder封装逻辑
BpBinder *proxy = binder->remoteBinder();
if (proxy == NULL) {
ALOGE("null proxy");
}
const int32_t handle = proxy ? proxy->handle() : ;
obj.type = BINDER_TYPE_HANDLE;
obj.binder = ; /* Don't pass uninitialized stack data to a remote process */
obj.handle = handle;
obj.cookie = ;
} else { // local类型的binder封装逻辑
obj.type = BINDER_TYPE_BINDER;
obj.binder = reinterpret_cast<uintptr_t>(local->getWeakRefs());
obj.cookie = reinterpret_cast<uintptr_t>(local);
}
} else {
obj.type = BINDER_TYPE_BINDER;
obj.binder = ;
obj.cookie = ;
} return finish_flatten_binder(binder, obj, out);
}
它根据传入binder的类型做不同的数据封装,在frameworks/native/include/binder/IBinder.h:139,可以看到IBinder声明了两个虚函数:
class IBinder : public virtual RefBase
{
public:
……
virtual BBinder* localBinder();
virtual BpBinder* remoteBinder();
……
};
并在frameworks/native/libs/binder/Binder.cpp:47定义了默认实现:
BBinder* IBinder::localBinder()
{
return NULL;
} BpBinder* IBinder::remoteBinder()
{
return NULL;
}
flat_binder_object这个数据结构在《Binder学习笔记(四)—— ServiceManager如何响应checkService请求》研究ServiceManager如何组织reply数据时遇到过,它定义在external/kernel-headers/original/uapi/linux/binder.h:57。对于不同的binder封装成的数据示意图如下:

然后flatten_binder(…)调用finish_flatten_binder(…),frameworks/native/libs/binder/Parcel.cpp:199
inline static status_t finish_flatten_binder(
const sp<IBinder>& /*binder*/, const flat_binder_object& flat, Parcel* out)
{
return out->writeObject(flat, false);
}
继续调用writeObject(…),frameworks/native/libs/binder/Parcel.cpp:1035
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
{
const bool enoughData = (mDataPos+sizeof(val)) <= mDataCapacity;
const bool enoughObjects = mObjectsSize < mObjectsCapacity;
if (enoughData && enoughObjects) {
restart_write:
// 如果空间足够,他把前面组装的flat_binder_object实体追加到mData里
*reinterpret_cast<flat_binder_object*>(mData+mDataPos) = val;
……
if (nullMetaData || val.binder != ) {
// mObjects记录每次向mData追加的flat_binder_object的偏移位置
mObjects[mObjectsSize] = mDataPos;
acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize);
mObjectsSize++;
} return finishWrite(sizeof(flat_binder_object));
}
……
}
总结一下:Parcel的数据区域分两个部分:mData和mObjects,所有的数据不管是基础数据类型还是对象实体,全都追加到mData里,mObjects是一个偏移量数组,记录所有存放在mData中的flat_binder_object实体的偏移量。Parcel的数据模型如下:

Binder学习笔记(五)—— Parcel是怎么打包数据的?的更多相关文章
- Binder学习笔记(九)—— 服务端如何响应Test()请求 ?
从服务端代码出发,TestServer.cpp int main() { sp < ProcessState > proc(ProcessState::self()); sp < I ...
- Binder学习笔记(十二)—— binder_transaction(...)都干了什么?
binder_open(...)都干了什么? 在回答binder_transaction(...)之前,还有一些基础设施要去探究,比如binder_open(...),binder_mmap(...) ...
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- (转)Qt Model/View 学习笔记 (五)——View 类
Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- golang学习笔记8 beego参数配置 打包linux命令
golang学习笔记8 beego参数配置 打包linux命令 参数配置 - beego: 简约 & 强大并存的 Go 应用框架https://beego.me/docs/mvc/contro ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
随机推荐
- java常用的空对象 null
- 编译适用于TP-Link WR703N的OpenWRT固件
编译适用于TP-Link WR703N TP-Link MR11U 以及使用AR9331芯片组的单WAN/LAN复用口的路由. 注:刷机有风险,刷机需谨慎.一般情况下是不会失败的,若无法通过捅Rese ...
- JavaScript实现重置表单(reset)的方法
转自:https://www.jb51.net/article/63305.htm <!DOCTYPE html> <html> <head> <script ...
- (修改)oracle11g监听多台主机配置,用pl/sql连接操作多个数据库详解
很多朋友在开发项目中并不是每个人用一个数据库,而是有单独的一台主机作为开发的数据库服务器,这样,就需要我们的开发人员去连接它. 首先是进入oracle的 Net Mananger:
- python的面向对象编程
面向对象编程是一种程序的范式,它把程序看成是对不同对象的相互调用,对现实世界建立的一种模型. 面向对象编程的基本思想,类和实例.类用于定义抽象对象,实例根据类的定义被创建出来. 在python当中我们 ...
- python爬虫(1)--Urllib库的基本使用
这里使用python2.7,pycharm进行代码编写 1.爬一个静态网页示例 import urllib2 response = urllib2.urlopen("http://www.b ...
- 使用JSONObject类来生成json格式的数据
JSONObject类不支持javabean转json 生成json格式数据的方式有: 1.使用JSONObject原生的来生成 2.使用map构建json格式的数据 3.使用javabean来构建j ...
- tortoisesvn 本项目的忽略项
https://tortoisesvn.net/docs/release/TortoiseSVN_en/tsvn-dug-propertypage.html Adding and Editing Pr ...
- MSSQL grant权限
--创建登录名 create login test_user with password='123456a.'; --创建用户 create user test_user for login test ...
- HDOJ 4802 GPA
Problem Description In college, a student may take several courses. for each course i, he earns a ce ...