进程间的数据传递和载体 Parcel
1. parcel设置相关
dataSize();当前已经存储的数据大小
setDataCapacity(int size);设置Parcel的空间大小
setDataPosition(int post);改变Parcel中的读写位置
dataAvail():可读数据大小;
dataCapaCity();当前Parcel的存储能力
dataPosition();数据的当前位置
dataSize();当前Parcel所包含的数据大小
2. 写入的数据类型
primitives,primitive Arrays
遵循Parcelables协议的对象 例:Bundles
3. Active Objects
Parcel可以读取原来写入的实例,限Active Object类型
这种对象主要有两类:Binder,FileDescription
4. 序列化方式
Serializable:需要手动设置serialVersionUID的值。如果不设置系统会计算当前类的hash值并赋给serialVersionUID,当增删了成员变量时,就会导致反序列化失败,程序crash。
特点:使用简单,开销大,序列化和反序列化的过程中需要大量I/O操作
Parcelable
特点:Android中的序列化方式,使用稍微复杂,效率高,主要用在内存序列化。
5. Parcel 源码分析
Parcel->obtain();系统预先生成一个parcel池,大小为6,如果已用完则重新创建
nativeCreate() : Parcel.java只是一个简单的中介,最终所有类型的读写操作都是通过本地代码实现
写入方和读取方所使用的协议必须是完全一致的
binder驱动与协议
Android系统把Binder注册成misc device类型的驱动。
binder_miscdev = {
.minor = MISC_DYNAMIC_MINOR,/*动态分配此设备号*/
.name = "binder",/*驱动名称*/
.fops = &binder_fops /*Binder驱动支持的文件操作*/
}
misc_register(&binder_miscdev); //驱动注册
file_operatons结构体
static const struct file_operations binder_fops = {
.owner = THIS_MODULE,
.poll = binder_poll,
.unlocked_ioctl = binder_ioctl,
.mmap = binder_mmap,
.open = binder_open,
.flush = binder_flush,
.release = binder_release,
}
”DNS“服务器--ServiceManager[Binder Server]
1.init.rc 启动serviceManager程序
2.ServiceManager的构建
binder_open()打开Binder设备做好初始化
binder_become_context_manager(bs) 将自己设置为Binder的大管家。
binder_loop(bs,svcmgr_handler);// 进入循环等待客户端请求
binder_parse(); 处理客户端请求
获取ServiceManager服务--设计思考
1.ProcessState专门管理每个应用进程中的Binder操作
2.IPCThreadState是与Binder驱动进行实际命令通信的
Clien->ServiceManagerProxy->parcel->ProcessState->BpBinder->IPCThreadState ->/dev/binder->ServiceManager(反之亦然)
ServiceManagerProxy
ServiceManager.java -> getIServiceManager() -> ServiceManagerNative.java -> asInterface(BinderInternal.getContextObject()这个方法和本地的ServiceManager建立起了关系) -> queryLocalInterface -> ServiceManagerProxy ->BidnerProxy
IBinder和BpBinder
java层:ServiceManagerProxy - > IBinder[是mRemote -> BinderProxy]** BinderProxy是通过内存地址记录远程IBinder的**
native层:android_os_BinderInternal_getContextObject() -> ProcessState::self->getContextObject(NULL)返回一个BpBinder,由javaObjectForIbinder(env,b)函数通过JNI的NewObject()转为一个BinderProxy
BinderProx->transact()
通过JNI的GetIntField获取int值即BpBinder对象的内存地址
IBinder* traget= (IBinder*)env->GetIntField(obj,gBinderProxyOffsets.mObject);
BpBinder->transact()->IPCThreadState->transact()
ProcessState 和 IPCThreadState
ProcessState关键点
- 保证同一个进程只有一个ProcessState实例存在;而且只有在ProcessState对象创建时才打开Binder设备以及做内存映射。
- 向上层提供IPC服务
- 与IPCThreadState分工合作,各司其职
self()->创建ProcessState实例
ProceessState构造函数中调用了open_driver() 和 mmap();
BidnerInternal中的getContextObject()最终实现在ProcessState中
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& caller){
return getStrongProxyForHandle(0);//传入0,代表ServiceManager
}
IPCTHreadState
- 线程中的单实例
- THread Local Storage 保证一个线程只有一个实例
BpBinder中调用了IPCThreadState::self( ) -> incWeakHandle(handle);
wait_event_interruptible(wq,condition) 调用者进程暂时挂起,直到目标进程返回结果后,Binder再唤醒等待的进程。
Binder Client
bindService启动其他进程的Service
- 应用程序填写Intent,调用binderService ContextImpl.java -> bindServiceCommon() -> ActivityManager.java -> getService() -> ServiceManager.java -> getService("activity") -> return IActivityManager.Stub -> bindService() -> ActivityManagerService