进程间通信BInder笔记

208 阅读3分钟

进程间的数据传递和载体 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)函数通过JNINewObject()转为一个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