binder传输机制

本文详细解析了BpBinder调用BBinder的过程,包括客户端如何通过BpGoodbyeService发起请求,以及请求如何被封装并通过Binder驱动传递给服务端。深入探讨了Binder通信机制中的关键组件和数据结构。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本节讲述BpBinder调用BBinder的过程,我们以client使用server提供的服务源码来分析。假设server向serviceManager注册了Goodbye服务(binder初始化有说),client获取了Goodbye服务。

client应用程序调用代理类对象方法BpGoodbyeService::saygoodbye_to("android")


Parcel对象提供了很多方法去封装数据到缓冲区,或者读取缓冲区的数据,注意在Parcel缓冲区写入字符串会先写入字符串的长度

data的缓冲区是这样分布的:


封装好数据后调用remote()->transact()。前面我们说过remote()返回的是binder引用对象Bpbinder,所以remote()->transact()就会调用到BpBinder的transact()函数。


BpBinder::transact()会调用binder线程对象transact函数,注意参数它增加了一个mHandle参数,也就是binder引用对象的handle值。这里它对binder实体对象BBinder的引用编号为1(handle=1)。


IPCThreadState::transact()会有两个步骤

1、writeTransactionData()封装数据

2、waitForResponse()发送数据并等待回复


1、writeTransactionData()


继续封装参数的数据到线程缓冲区,注意参数data和线程缓冲区mout都是Parcel对象。

mOut的缓冲区是这样分布的:


2、waitForResponse()


waitForResponse会在死循环通过talkWithDriver向驱动发送数据,并在talkWithDriver里面阻塞,直到有数据返回,然后通过case-by-case解释读到的cmd。要注意很多返回的cmd处理只是简单的break处理,然后循环talkWithDriver再向驱动发送数据,阻塞等待驱动返回的数据,直到解释goto finish的命令才结束死循环。

再看talkWithDriver把线程缓冲区mout的数据封装成binder_write_read 结构体发送到驱动


它最终会通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)发送数据到驱动,这个线程阻塞到这里。直到驱动返回,返回数据的就在bwr.read_buffer缓冲区,bwr.read_consumed是返回数据的长度。可以看到它把数据放到reply缓冲区,reply依然是Parcel对象。


总结为图:



ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)

client进入内核空间,调用到binder驱动的binder_ioctl。cmd为BINDER_WRITE_READ,参数bwr.write_size  和 bwr.read_size都大于0,所有依次调用

1、binder_thread_write()

2、binder_thread_read()


1 binder_thread_write()


binder_transaction


其实server就是在binder_thread_read上wait_event_interruptible_exclusive上睡眠了,binder_transaction把它唤醒了,继续执行。我们先忽略client的binder_thread_read,直接看看server的binder_thread_read。

binder_thread_read()


client在用户空间把binder_transaction_data传给client内核空间,client内核空间在binder_transaction函数里面把binder_transaction_data整理成一个事务binder_transaction结构体,并通过链表链入到server内核空间的proc->todo事务队列,并唤醒server内核空间的proc->wait等待队列server会继续在binder_thread_read函数wait_event_interruptible_exclusive上唤醒并继续执行。server把proc->todo链表中的事务binder_transaction取出来,并重新组织binder_transaction_data传递给server的用户空间。要注意,client用户空间结构体binder_transaction_data.target.handle为Bpbinder的handle值,到了server的内核空间binder_thread_read,server把binder_transaction_data.target.cookie附上值,cookie值正是BBinder在server用户空间中的地址。


待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值