目录
binder_transaction和binder_work
BpBinder.transact->IPCThreadState.transact
waitForResponse->talkWithDriver
talkWithDriver->ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
Ioctl->binder_ioctl_write_read
BC_TRANSACTION->binder_transaction
BR_TRANSACTION->BBinder->transact
binder c
ServiceManager
Servicemanager 接口及实现
- 自动生成C++ AIDL 及实现BnServiceManager接口
out\soong\.intermediates\frameworks\native\libs\binder\libbinder\android_arm64_armv8-a_cortex-a53_shared\gen\aidl\android\os\IServiceManager.h (......)
namespace android {
namespace os {
class IServiceManager : public ::android::IInterface {
public:
DECLARE_META_INTERFACE(ServiceManager)
}
out\soong\.intermediates\frameworks\native\libs\binder\libbinder\android_arm64_armv8-a_cortex-a53_shared\gen\aidl\android\os\BnServiceManager.h
out\soong\.intermediates\frameworks\native\libs\binder\libbinder\android_arm64_armv8-a_cortex-a53_shared\gen\aidl\android\os\BpServiceManager.h
out\soong\.intermediates\frameworks\native\libs\binder\libbinder\android_arm64_armv8-a_cortex-a53_shared\gen\aidl\frameworks\native\libs\binder\aidl\android\os\IServiceManager.cpp
BpServiceManager/BnServiceManager 都在这里实现
- 实现BnServiceManager即ServiceManager
frameworks\native\cmds\servicemanager\servicemanager.rc
service servicemanager /system/bin/servicemanager
frameworks\native\cmds\servicemanager\ServiceManager.h
class ServiceManager : public os::BnServiceManager, public IBinder::DeathRecipient {
public:
ServiceManager(std::unique_ptr<Access>&& access);
~ServiceManager();
frameworks\native\cmds\servicemanager\ServiceManager.cpp
这里实现了BnServiceManager
- ServiceManager 主程序
frameworks\native\cmds\servicemanager\main.cpp
- ServiceManager 外壳
frameworks\native\libs\binder\include\IServiceManager.h
namespace android {
// ----------------------------------------------------------------------
/**
* Service manager for C++ services.
*
* IInterface is only for legacy ABI compatibility
*/
class IServiceManager : public IInterface
{
}
frameworks\native\libs\binder\IServiceManager.cpp
namespace android {
using AidlServiceManager = android::os::IServiceManager;
using android::binder::Status;
这里其实就是通过AidlServiceManager 的接口来实现接口
}
Servicemanager 启动
frameworks\native\cmds\servicemanager\servicemanager.rc
service servicemanager /system/bin/servicemanager
frameworks\native\cmds\servicemanager\main.cpp
int main(int argc, char** argv) {
const char* driver = argc == 2 ? argv[1] : "/dev/binder";
sp<ProcessState> ps = ProcessState::initWithDriver(driver);//<!-- 创建全局ProcessState/IPCThreadState ,打开/dev/binder
ps->setThreadPoolMaxThreadCount(0);
ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());
if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
//<!--将ServiceManager加入mNameToService列表
LOG(ERROR) << "Could not self register servicemanager";
}
LOG(ERROR) << "register servicemanager";
IPCThreadState::self()->setTheContextObject(manager);
//<!--ServiceManager保存到IPCThreadState
ps->becomeContextManager(nullptr, nullptr);
//<!-- 这里创建flat_binder_object,发送命令BINDER_SET_CONTEXT_MGR_EXT给到驱动
flat_binder_object obj {
.flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
};
int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);
//<!--下面启动binder主线程添加到binder 线程池循环,等待发起端发送命令和数据,这些命令和数据通过binder 驱动发送给serviceManager的。
sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
BinderCallback::setupTo(looper);
ClientCallbackCallback::setupTo(looper, manager);
while(true) {
looper->pollAll(-1);
}
// should not be reached
return EXIT_FAILURE;
}
Binder c 一些重要数据结构对象
ProcessState和PCThreadState
Binder c在用户空间是通过ProcessState/IPCThreadState来进行进程间通讯,是一个单实例,可以简单理解为一个C程序(进程)中只有一个ProcessState;IPCThreadState通过线程特有数据(TSD: Thread-Specific Data)或者线程局部存储(TLS: Thread-Local Storage)保证单实例,就是通常说的用于IPC通讯的一个binder 线程,线程池中是在PoolThread 中创建。
创建ProcessState 时就会Open_driver 打开/dev/binder设备用于跟binder 通讯,在驱动端会创建binder_proc等。
binder_proc和binder_thread
在用户空间中一个进程对应一个ProcessState,一个用于进程间通信的线程对应一个IPCThreadState。而在内核空间中也提供了对应的数据结构:binder_proc和binder_thread。binder_proc与ProcessState一一对应,binder_thread与IPCThreadState一一对应。
binder_thread与IPCThreadState构建了用户空间和内核空间的的通信通道。
binder_node和binder_ref
在binder驱动binder_node是BnXXXService对应,在本binder_proc里面,binder_ref可以认为跟BpXXXService对应,也就是本binder_proc引用其它binder_proc中的binder_node 对象;也就是我们通常说的实体对象(本地对象)跟引用或代理对象(远端对象);在用户空间,通过handle 来关联BpXXXService(对应BnXXXService)
binder_transaction和binder_work
binder_transaction 用于驱动binder_thread 间交互事务数据。binder_work是事务类型
binder_alloc和binder_buffer
binder_buffer 记录具体分配的一个buffer信息,比如是否free,属于哪个binder_node 等;binder_alloc就是binder内存分配管理。
binder_ioctl 进入到kernel
__user宏简单告诉编译器(通过 noderef)不应该解除这个指针的引用(因为在当前地址空间中它是没有意义的)。
(void __user *)arg 指的是arg值是一个用户空间的地址,不能直接进行拷贝等,要使用如copy_from_user,copy_to_user等函数。默认是内核空间,因为这是驱动,是在内核空间运行的。
假如用户空间写为:
int i = 0;
ioctl(fd, XXXXX, i);
内核空间需要写为
get_user(xxx, (int __user *)arg);
假如用户空间写为:
int i = 0;
ioctl(fd, XXXXX, &i);
则内核空间需要写为:
copy_from_user(&xxx, (void __user *)arg, size);
android Binder 线程创建
frameworks/base/cmds/app_process/app_main.cpp
virtual void onStarted()
{
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
AndroidRuntime* ar = AndroidRuntime::getRuntime();
ar->callMain(mClassName, mClass, mArgs);
IPCThreadState::self()->stopProcess();
hardware::IPCThreadState::self()->stopProcess();
}
virtual void onZygoteInit()
{
sp<ProcessState> proc = ProcessState::self();
proc->startThreadPool();
}
virtual void onExit(int code)
{
if (mClassName.isEmpty()) {
// if zygote
IPCThreadState::self()->stopProcess();
hardware::IPCThreadState::self()->stopProcess();
}
AndroidRuntime::onExit(code);
}
binder驱动简述
Binder驱动是Android专用的,但底层的驱动架构与Linux驱动一样。binder驱动在以misc设备进行注册,作为虚拟字符设备,没有直接操作硬件,只是对设备内存的处理,主要是驱动设备的初始化(binder_init),打开(binder_open),映射(binder_mmap),数据操作(binder_ioctl)。
通过init(),创建/dev/binder设备节点
通过open(),获取Binder Driver的文件描述符
通过mmap(),在内核分配一块内存,用于存放数据
通过ioctl(),将IPC数据作为参数传递给Binder Driver
用户态的程序调用Kernel层驱动是需要陷入内核态,进行系统调用(syscall),比如打开Binder驱动方法的调用链是:open()->__open()->binder_open()。open()为用户空间的方法, _open()是系统调用中相应的处理方法,通过查找,对应调用到内核binder驱动的binder_open方法。
Client进程通过RPC(Remote Procedure Call Protocol)与Server通信,可以简单的分为三层,驱动层、IPC层、业务层。client和server共同协商好的统一方法,RPC数据、code、handle、协议这四项组成了IPC的层的数据,通过IPC层进行数据传输,而真正在Client和Server两端建立通信的基础设施是Binder Driver。
例如:当AMS的client向ServiceManger注册服务的过程中,IPC层的数据组成为:handle=0,RPC数据为AMS,code为ADD_SERVICE_TRANSACTION,binder协议为BC_TRANSACTION。
addService 流程分析
服务端
int main(int argc, char** argv)
{
......
sp<ProcessState> proc(ProcessState::self());
sp<IServiceManager> sm = defaultServiceManager();
sm->addService(String16(MY_SERVICE), new BnMyService());
ProcessState::self()->startThreadPool(); <!-- 这里会创建一个PoolThread 线程,线程里面会创建IPCThreadState并调用joinThreadPool将该PoolThread线程加入。Binder:10882_1
IPCThreadState::self()->joinThreadPool();<!--这里就是创建IPCThreadState并调用joinThreadPool 将当前线程,也就是main 这个线程加入。10882:10882
}
defaultServiceManager()流程分析
frameworks\native\libs\binder\IServiceManager.cpp
sp<IServiceManager> defaultServiceManager()
{
std::call_once(gSmOnce, []() {
sp<AidlServiceManager> sm = nullptr;
while (sm == nullptr) {
sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
<!-- 这里创建ProcessState对象,这里查找ProcessState中跟handle 为0 对应的BpBinder,由于是刚创建的ProcessState ,所以是查询不到BpBinder。
<!--这里最后是interface_cast<AidlServiceManager>(BpBinder),等价
sp<IServiceManager> IServiceManager::asInterface(BpBinder),这里相当
new BpServiceManager(BpBinder);
}
gDefaultServiceManager = new ServiceManagerShim(sm);
});
return gDefaultServiceManager;
}
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
sp<IBinder> context = getStrongProxyForHandle(0);
<!-- 这里查询ProcessState中与handle 0 对应的BpBinder
return context;
}
sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
sp<IBinder> result;
AutoMutex _l(mLock);
handle_entry* e = lookupHandleLocked(handle);
<!-- 这里查询ProcessState中与handle 0 对应的BpBinder
if (e != nullptr) {
IBinder* b = e->binder;
<!-- 这里查询ProcessState中与handle 0 对应的BpBinder,b == nullptr说明没有
if (b == nullptr || !e->refs->attemptIncWeak(this)) {
if (handle == 0) {
Parcel data;
status_t status = IPCThreadState::self()->transact(
0, IBinder::PING_TRANSACTION, data, nullptr, 0);
<!-- 如果查询handle 0 对应的BpBinder是发送一个Binder cmd 给驱动。
if (status == DEAD_OBJECT)
return nullptr;
}
b = BpBinder::create(handle);
<!-- 没有查询到handle 0 对应的BpBinder,则创建,并加入列表记录,下次查询就能查到,这里创建BpBinder时,IPCThreadState 是已经创建了的。
e->binder = b;
if (b) e->refs = b->getWeakRefs();
<!-- 增加弱引用 result = b;
} else {
result.force_set(b);
e->refs->decWeak(this);
<!-- 如果查询handle 对应的BpBinder则增加弱引用即可
}
}
return result;
}
interface_cast<AidlServiceManager>(BpBinder)
ServiceManager 服务比较特殊,其BBinder(服务) 有保存在IPCThreadState中(the_context_object),对应的handle 是0;每次获取BpServiceManager前需要向binder-driver发送PING_TRANSACTION来确定ServiceManager存在,否则返回DEAD_OBJECT。
BpBinder::create(handle)调用时,则会向mOut 写入对应BC_INCREFS\BC_ACQUIRE命令,分别对handle 对应的binder_ref 的弱/强引用,同时BpBinder 也会增加对ProcessState 的引用,但是命令要在之后有调用talkwithdriver才会发送。
addService
流程图
sm->addService(String16(MY_SERVICE), new BnMyService());
这里会执行BpBinder.transact->IPCThreadState.transact向驱动发送命令(这里是BpServiceManager,defaultServiceManager创建的BpBinder),将BnMyService 同步flattenBinder 发送给驱动
writeStrongBinder-》flattenBinder-》writeObject、acquire_object
status_t Parcel::writeObject(const flat_binder_object& val, bool nullMetaData)
{
// Need to write meta-data?
if (nullMetaData || val.binder != 0) {//<!--如果是本地对象弱引用val.binder不为空,或者为handle
mObjects[mObjectsSize] = mDataPos;
acquire_object(ProcessState::self(), val, this, &mOpenAshmemSize);
mObjectsSize++;
}
return finishWrite(sizeof(flat_binder_object));
}
static void acquire_object(const sp<ProcessState>& proc,
const flat_binder_object& obj, const void* who, size_t* outAshmemSize)
{
switch (obj.hdr.type) {
case BINDER_TYPE_BINDER:
if (obj.binder) {
reinterpret_cast<IBinder*>(obj.cookie)->incStrong(who);//<!--BBinde增加对parcel 引用
}
return;
case BINDER_TYPE_HANDLE: {
const sp<IBinder> b = proc->getStrongProxyForHandle(obj.handle);<!--BpBinder增加对parcel 引用
if (b != nullptr) {
b->incStrong(who);
}
return;
}
case BINDER_TYPE_FD:
}
BpBinder.transact->IPCThreadState.transact
writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);将Parcel 及额外信息写入binder_transaction_data,再将binder_transaction_data写入mOut.
将需要发送的数据封装
- data_size,binder_transaction的数据大小
- data.ptr.buffer,binder_transaction数据的起始地址
- offsets_size,记录flat_binder_object结构体的个数
- data.ptr.offsets,记录flat_binder_object结构体的数据偏移量
waitForResponse->talkWithDriver
将数据封装为binder_write_read 通过talkWithDriver调用ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)将封装的数据发送给到驱动,发送给到驱动后,等待驱动端返回BR命令,通过mIn读取发送给到客户端命令(BR_TRANSACTION_COMPLETE、BR_REPLY)。
这里默认是接收数据,只有当mIn里面没有数据,才会发送mOut里面数据,也就是从Binder 驱动接收数据优先发送数据给驱动,这里根据是否接收发送数据将mIn/mOut 写入binder_write_read,正常情况是mIn为空,从而会向驱动发送数据,同时会接收数据。
talkWithDriver->ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)
这里将封装好的binder_write_read 数据,通过命令BINDER_WRITE_READ发送给驱动,
binder_ioctl 这里会获取binder_proc(binder_open 这里会关联创建binder_proc),通过binder_get_thread从binder_proc->threads.rb_node 中遍历binder_proc 是否与当前task pid 一致,一致则找到了通讯的binder_thread,否则就创建binder_thread用于通讯。根据BINDER_WRITE_READ 命令执行binder_ioctl_write_read。
这里binder_proc:binder_thread 就是平时binder log 中的pid:tid
from 29016:29283 to 29464:29687
Ioctl->binder_ioctl_write_read
这里从用户空间将binder_write_read 复制到驱动空间binder_write_read,由于client 发送的内容不为空(bwr.write_size>0),所以执行binder_thread_write,同时由于mIn为空,bwr.read_size > 0,会执行binder_thread_read
BC_TRANSACTION->binder_transaction
这里从binder_write_read里面获取发送给到驱动命令字段BC_TRANSACTION,执行
binder_transaction
这里主要做的事情有:
1、解析用户空间发送过来的数据,即flat_binder_object(BnXXXService)
2、从binder_proc 里面没有查询到fp->binder对应的binder_node,则为该BnXXXService创建binder_node,保存了BnXXXService、binder_proc等信息,并创建对端(目标)内核进程(BnServiceManager)对这个node 的引用binder_ref(可以根据binder_ref 找到binder_node),分配一个handle,并将flat_binder_object 写入(目标)内核进程(BnServiceManager)的binder_buffer.
3、在发起端binder_thread 进程添加BINDER_WORK_TRANSACTION_COMPLETE 事务,ServiceManager binder_thread 添加BR_TRANSACTION_COMPLETE 事务。
4、发起端binder_thread进入休眠,唤醒ServiceManager binder_thread ,执行binder_thread_read。
【
这里从binder_write_read里面获取发送给到驱动命令字段BC_TRANSACTION,执行
binder_transaction
这里从binder_thread_read指向用户空间的binder_transaction_data复制到kernel 空间binder_transaction_data。根据target->handle ,如果为0 ,直接从binder_proc->binder_context 中获取ServiceManager对应binder_node,从binder_node 获取目标binder_proc;如果非0,则根据对应的handle 从binder_proc->refs_by_desc中查询跟handle 相等的binder_ref,再从binder_ref 中获取目标binder_node,从binder_node 获取目标进程binder_proc;遍历发送端binder_thread->todo 队列(binder_work),如果有其类型为BINDER_WORK_TRANSACTION,则说明该binder_thread线程当前已经有事务,不能允许发送outing transaction,通讯出错返回;遍历发送端binder_thread->transaction_stack(binder_transaction),其首指针对应的binder_thread 需要等于该线程id,否则通讯出错返回,遍历binder_transaction,其进程跟目标进程(node对应的)一样,则找到了目标线程;创建目标进程binder_buffer,即目标binder_proc->alloc,根据binder_transaction_data数据来创建,填充binder_transaction,填充信息包括binder_transaction_data 里面信息,binder_buffer信息等,复制binder_transaction_data数据到binder_buffer;根据复制的数据,判断flat_binder_object类型,由于添加服务类型(BBinder)是BINDER_TYPE_BINDER,调用binder_translate_binder从发送端proc->nodes.rb_node中查询跟flat_binder_object->binder(BBinder弱引用)相等node,没有则创建,并将flat_binder_object->binder,flat_binder_object->cookie填充node,node->binder_work类型为BINDER_WORK_NODE;目标进程增加node 对应的binder_ref,即ServiceManager增加中增加binder_ref,也就是目标进展中增加了根据handle对应的binder_ref,其handle 是在之前的最大handler 上加1,修改flat_binder_object类型为BINDER_TYPE_HANDLE,binder、cookie清0,handle设置为binder_ref->binder_ref_data->desc ,也就是刚才的handle,将flat_binder_object复制到binder_transaction;在发送binder_thread线程todo 队列添加类型BINDER_WORK_TRANSACTION_COMPLETE的binder_work,因为这种类型不急,所以没有设置process_todo为true,并将binder_transaction->binder_work类型设置为BINDER_WORK_TRANSACTION,将binder_transaction->from_parent设置为发送线程transaction_stack,发送线程binder_thread->transaction_stack设置为binder_transaction;调用binder_proc_transaction,将刚才BINDER_WORK_TRANSACTION 类型binder_work加入目标线程todo队列,并设置process_todo为true,如果没有binder_thread,则加入目标进程todo队列,唤醒目标线程,执行事务。
】
服务端binder_thread_read
service_manager binder_thread线程一旦空闲便是停留在binder_thread_read()方法来处理进程/线程新的事务, 收到的是BINDER_WORK_TRANSACTION事务,向用户服务端线程写入BR_TRANSACTION,这里是ServiceManager。如果是其它服务,根据target_node中获取trd->target.ptr,trd->cookie(BnXXXService对应的本地binder对应的弱引用及Binder),填充flat_binder_object,封装成binder_write_read写入mIn指针地址;mIn中有数据,从而用户空间服务进程的poolthread 执行BR_TRANSACTION命令,从mIn中读取数据到binder_transaction_data,并通过ipcSetDataReference获取flat_binder_object对象,获取到BnXXXService 弱应用,执行BBinder->transact。执行完将通过BC_REPLY 将结果发送给服务端驱动,服务端驱动执行binder_thread_write,处理BC_REPLY,在服务端binder_thread->todo 添加BINDER_WORK_TRANSACTION_COMPLETE类型binder_work,在发起端binder_thread->todo添加BR_WORK_TRANSACTION将flat_binder_object写入binder_write_read->read_buffer,唤醒发起端binder_thred.
发起端binder_thread_read
1、bwr.read_size > 0, 便开始执行binder_thread_read();
这里从发送端binder_thread->todo 里面取到BINDER_WORK_TRANSACTION_COMPLETE类型binder_work,将BR_TRANSACTION_COMPLETE写入客户端用户空间binder_write_read->read_buffer。
- 一次Binder_ioctl完成,接着回到用户空间方法talkWithDriver()。
- 这时mIn有可读数据, 回到waitForResponse()方法,执行BR_TRANSACTION_COMPLETE过程
- 对于oneway的操作, 这次Binder通信便完成, 否则还是要等待Binder服务端的返回.
- 驱动端继续执行BR_WORK_TRANSACTION事务,向用户空间发送BR_REPLY,并写入服务返回的数据。
- 发起端执行BR_REPLY,从reply parcel 获取服务端返回的数据。
BR_TRANSACTION->BBinder->transact
这里执行到BnServiceManager::onTransact
readStrongBinder->unflattenBinder
这里读取ipcSetDataReference方法获取的flat_binder_object对象,在binder_transaction中已经修改flat_binder_object类型为BINDER_TYPE_HANDLE,handle设置为binder_ref->binder_ref_data->desc,从而根据该handle 创建BpBinder,这里会增加对服务对应的binder_ref的引用+1,从parcel 中获取cookie(BnXXXServer),加入mNameToService,从而调用时直接从列表获取。
BR_TRANSACTION->sendReply
在serviceManager用户进程执行完BBinder->transact,就会向驱动发送BC_REPLY命令
sendReply会进入waitForResponse等待驱动应答BR_TRANSACTION_COMPLETE,这样就向serviceManager对应的kernel binder_thread 发送BC_REPLY,通过binder_transaction再向binder_thread线程todo 队列添加类型BINDER_WORK_TRANSACTION_COMPLETE的binder_work,在目标进程添加BINDER_WORK_TRANSACTION的binder_work;serviceManager binder_thread 执行binder_thread_read执行BINDER_WORK_TRANSACTION_COMPLETE事务,发送BR_TRANSACTION_COMPLETE,目标进程binder_thread_read执行BINDER_WORK_TRANSACTION,向用户端发送BR_REPLY,一次完整通讯完成。
getService流程
int main()
{
sp < IServiceManager > sm = defaultServiceManager(); //sm 为BpServiceManager
sp < IBinder > binder = sm->getService(String16(MY_SERVICE));//这里调用BpBinder.transact->IPCThread.transact
// binder 为BpBinder ,service为BpMyService 对象
sp<IMyService> service = IMyService::asInterface(binder);
service->sendInt(-i);
return 0;
}
defaultServiceManager();创建BpBinder,即BpServiceManager
1、调用BpBinder->transact,再调用IPCThreadState->transact 将数据通过binder_io_write_read发送给到客户端对应的kernel binder_thread,binder_thread执行binder_thread_write获取用户空间数据命令BC_TRANSACTION,执行binder_transaction,这里由于是BpServiceManager,所以根据handle 0 获取到service_manager对应的binder_node,创建对其binder_node的引用。
2、在客户端(发起端)对应的binder_thread->todo 添加
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE类型binder_work,进入休眠;
在目标(当前是ServiceManager服务)kernel binder_thread->todo添加
t->work.type = BINDER_WORK_TRANSACTION类型binder_work;
ServiceManager内核binder_thread被唤醒,在binder_thread_read中执行BINDER_WORK_TRANSACTION事务, 发送BR_TRANSACTION事务命令和命令码GET_SERVICE到serviceManager用户空间,BnServiceManager比较特殊,是保存在ServiceManager IPCThreadState中,执行BBinder->transact到BnServiceManager->onTransact处理BR_TRANSACTION,即其根据服务名字查询到对应的cookie(BnXXXService、handle相关),执行writeStrongBinder写入parcle,将其发送给到ServiceManager内核binder_thread,即通过sendReply发送BC_REPLY。内核binder_thread处理BC_REPLY,根据handle查询到服务对应binder_ref,再根据binder_ref查询都binder_node,创建客户端(发起端)对该binder_node 的引用并分配对应handle(handle=1),将这些信息给到客户端对应的binder_thread,并在ServiceManager对应的binder_thread->todo 添加
tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE类型binder_work,执行并向ServiceManager 用户进程发送BR_TRANSACTION_COMPLETE。
4、客户端对应的binder_thread被唤醒,执行binder_thread_read处理BINDER_WORK_TRANSACTION_COMPLETE类型binder_work,向客户端(发起端)IPCThreadState 发送BR_TRANSACTION_COMPLETE,客户端处理该命令进入等待客户端kernel reply。
5、客户端对应kenel 端向发起端用户空间IPCThreadState发送BR_REPLY,客户端处理BR_REPLY,通过ipcSetDataReference将发送的数据写入parcel ;再通过readNullableStrongBinder从parcel 读取对应flat_binder_object,这里其handle =1 ,创建BpBinder(handle=1),增加对binder_ref 引用计数,再创建BpXXXService(BpBinder)。这样就可以直接跟服务端通讯了。
IPCThreadState既作为客户端,又作为服务端
关系图
作为客户端(发起端)
transact() -- writeTransactionData() -- waitForResponse() -- talkWithDriver() -- reply->ipcSetDataReference()
virtual status_t addService(const String16& name, const sp<IBinder>& service,
bool allowIsolated)
{
Parcel data, reply;
data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
data.writeString16(name);
data.writeStrongBinder(service);
data.writeInt32(allowIsolated ? 1 : 0);
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
return err == NO_ERROR ? reply.readExceptionCode() : err;
}
status_t IPCThreadState::transact(int32_t handle,
uint32_t code, const Parcel& data,
Parcel* reply, uint32_t flags)
{
err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
<!--向mOut里面写入发送的数据
if ((flags & TF_ONE_WAY) == 0) {
if (reply) {
err = waitForResponse(reply);<!--同步调用,就需要等待Binder 驱动返回
} else {
Parcel fakeReply;
err = waitForResponse(&fakeReply);
}
} else {
err = waitForResponse(nullptr, nullptr);
}
return err;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break;
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:
if (!reply && !acquireResult) goto finish;
break;
case BR_REPLY:
{
binder_transaction_data tr;
err = mIn.read(&tr, sizeof(tr));
reply->ipcSetDataReference(
reinterpret_cast<const uint8_t*>(tr.data.ptr.buffer),
tr.data_size,
reinterpret_cast<const binder_size_t*>(tr.data.ptr.offsets),
tr.offsets_size/sizeof(binder_size_t),
freeBuffer, this);
goto finish;
}
finish:
return err;
}
这个图就是客户端通过BpBinder 中创建的IPCThreadState.transact将命令参数BC_*写入mOut 发送给Binder 驱动,进入等待;Binder 驱动收到后,处理并将返回数据写入mIn。PoolThread主线程Binder_X里面获取到mIn中BR_*数据,从数据中获取到BBinder地址,从而调用其transact,transact 调用OnTransact,从而调用服务端实现的方法,处理完,将结果写入mOut,并发送BC_*命令给到驱动;驱动收到命令,就会应答返送BR_*返回结果给到客户端,客户端取到数据。
作为服务端
startThreadPool--joinThreadPool() -- getAndExecuteCommand() -- talkWithDriver() -- executeCommand() -- sendReply() -- writeTransactionData() -- waitForResponse()
IPCThreadState::joinThreadPool(bool isMain)
{
mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
<!-- isMain 为true ,Poolthread 主线程
do {
processPendingDerefs();
<!--这里判断如果mIn里面没用数据,则清空mPendingWeakDerefs与mPendingStrongDerefs
result = getAndExecuteCommand();
<!--这里将mOut 数据发送给Binder 驱动,如果mIn里面没有数据,则会同时读Binder 返回的数据;mIn 里面的数据是Binder 驱动发过来的命令
if (result < NO_ERROR && result != TIMED_OUT && result != -ECONNREFUSED && result != -EBADF) {
LOG_ALWAYS_FATAL("getAndExecuteCommand(fd=%d) returned unexpected error %d, aborting",
mProcess->mDriverFD, result);
<!-- 如果跟Binder 驱动通讯出了问题,则挂掉系统
}
if(result == TIMED_OUT && !isMain) {
break;
<!-- 如果跟Binder 驱动通讯超时了,且不是Poolthread 主线程,则跳出循环,就结束该Binder线程
}
}while (result != -ECONNREFUSED && result != -EBADF);<!-- 循环跟Binder 通讯
mOut.writeInt32(BC_EXIT_LOOPER);<!-- Binder 线程退出,发送命令给Binder 驱动。
talkWithDriver(false);<!-- 发送数据给Binder 驱动,false表示不接收Binder 返回的数据
}
status_t IPCThreadState::getAndExecuteCommand(){
result = talkWithDriver();
if (result >= NO_ERROR) {
size_t IN = mIn.dataAvail();
if (IN < sizeof(int32_t)) return result; <!--Binder 驱动无数据返回需要处理,就返回
cmd = mIn.readInt32();<!--Binder 驱动返回的命令
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount++;<!-- 将执行线程计数+1
pthread_mutex_unlock(&mProcess->mThreadCountLock);
result = executeCommand(cmd);<!--执行Binder 驱动返回的命令
pthread_mutex_lock(&mProcess->mThreadCountLock);
mProcess->mExecutingThreadsCount--;<!--执行完线程计数-1
pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
pthread_mutex_unlock(&mProcess->mThreadCountLock);
}
return result;
}
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
binder_write_read bwr;
// Is the read buffer empty?
const bool needRead = mIn.dataPosition() >= mIn.dataSize();<!--mIn 是否为空,为空就可以再读取Binder 驱动返回的数据
const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;<!--mIn 里面的数据还没有处理完,则无需跟Binder 驱动通讯,返回继续处理mIn中命令;如果不再接收Binder 驱动返回数据,则强制将mOut 数据发送给Binder 驱动,但是不接收。
// This is what we'll read.
if (doReceive && needRead) {
bwr.read_size = mIn.dataCapacity();
bwr.read_buffer = (uintptr_t)mIn.data();
} else {
bwr.read_size = 0;
bwr.read_buffer = 0;
}
// Return immediately if there is nothing to do.
if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;
bwr.write_consumed = 0;
bwr.read_consumed = 0;
status_t err;
do {
if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
err = NO_ERROR;
else
err = -errno;
<!--循环,直到mOut 数据全部写入Binder 驱动
} while (err == -EINTR);
if (err >= NO_ERROR) {
if (bwr.write_consumed > 0) {
mOut.setDataSize(0);<!--将mOut 设置没有数据
processPostWriteDerefs();
<!--mPostWriteWeakDerefs、mPostWriteStrongDerefs引用清空
}
if (bwr.read_consumed > 0) {
mIn.setDataSize(bwr.read_consumed);<!--将mIn 设置为读到的数据长度
mIn.setDataPosition(0);
}
return NO_ERROR;
}
return err;
}
status_t IPCThreadState::executeCommand(int32_t cmd)
{
BBinder* obj;
RefBase::weakref_type* refs;
status_t result = NO_ERROR;
switch ((uint32_t)cmd) {
case BR_SPAWN_LOOPER:
mProcess->spawnPooledThread(false);
<!-- 创建Binder线程,这里是再PoolThread 中对应的IPCThreadState中创建的
break;
case BR_TRANSACTION_SEC_CTX:
case BR_TRANSACTION:{
if (tr.target.ptr) {
if (reinterpret_cast<RefBase::weakref_type*>(tr.target.ptr)->attemptIncStrong(this)) {
error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);
reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
<!--BBinder 中transact 是默认调用BBinder中OnTransact,但是服务端BnService 会覆写OnTransact,从而调用到服务端OnTransact,Ontransact 就是调用服务端的方法获取返回值到reply.这里其实可以认为是Binder 驱动将指针地址发过来了。
} else {
error = UNKNOWN_TRANSACTION;
}
} else {
error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
}
if ((tr.flags & TF_ONE_WAY) == 0) {
LOG_ONEWAY("Sending reply to %d!", mCallingPid);
if (error < NO_ERROR) reply.setError(error);
sendReply(reply, 0);
<!-- 返回数据
}
}
status_t IPCThreadState::sendReply(const Parcel& reply, uint32_t flags)
{
status_t err;
status_t statusBuffer;
err = writeTransactionData(BC_REPLY, flags, -1, 0, reply, &statusBuffer);
if (err < NO_ERROR) return err;
return waitForResponse(nullptr, nullptr);
}
status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
binder_transaction_data tr;
mOut.writeInt32(cmd);
mOut.write(&tr, sizeof(tr));
<!--将需要返回的数据写入mOut,命令为BC_REPLY,
return NO_ERROR;
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
uint32_t cmd;
int32_t err;
while (1) {
if ((err=talkWithDriver()) < NO_ERROR) break; <!--通过talkWithDriver将mOut 发送给Binder 驱动,mIn 获取Binder 驱动返回的内容
err = mIn.errorCheck();
if (err < NO_ERROR) break;
if (mIn.dataAvail() == 0) continue;
cmd = (uint32_t)mIn.readInt32();
switch (cmd) {
case BR_TRANSACTION_COMPLETE:<!-- 事务完成
if (!reply && !acquireResult) goto finish;
break;
default:
err = executeCommand(cmd);<!--执行命令
if (err != NO_ERROR) goto finish;
break;
}
}
<!--结束等待
finish:
if (err != NO_ERROR) {
if (acquireResult) *acquireResult = err;
if (reply) reply->setError(err);
mLastError = err;
}
return err;
}
参考链接
binder
oneway binder 调用导致vma 用完
https://blog.csdn.net/weiqifa0/article/details/100570446
BC_、BR_命令
https://blog.csdn.net/u013553529/article/details/21837089
https://blog.csdn.net/chijiandao3197/article/details/100930701
[16814:ssioncontroller]binder: 16814:16814 transaction failed 29189/-3, size 3700-8 line 3345
kernel-4.19/include/uapi/asm-generic/errno-base.h
#define ESRCH 3 /* No such process */
Binder 调用客户调用到服务进程
https://www.cnblogs.com/lmf-techniques/p/8926460.html
https://blog.csdn.net/weixin_30484247/article/details/99818252
https://blog.csdn.net/chijiandao3197/article/details/100930701
Binder 流图
https://blog.csdn.net/freekiteyu/article/details/70082302
IPC.waitForResponse
https://my.oschina.net/u/3168816/blog/824462
addService
https://blog.csdn.net/jltxgcy/article/details/26076149
https://blog.csdn.net/qq_38907791/article/details/89576209
例子
https://www.cnblogs.com/hzl6255/p/12105245.html
Binder 驱动数据结构
https://www.cnblogs.com/palance/p/5768748.html
https://my.oschina.net/u/3168816/blog/824462
文档链接
https://blog.csdn.net/jltxgcy/article/details/26076149
https://blog.csdn.net/jltxgcy/article/details/27638717
pthread 经典
https://www.cnblogs.com/sunminmin/p/4479952.html
https://blog.csdn.net/u013234805/article/details/24796569
https://blog.csdn.net/mitushutong11/article/details/51336136
http://blog.sina.com.cn/s/blog_e59371cc0102v29b.html
https://blog.csdn.net/freekiteyu/article/details/70082302
Binder-java-native 层
https://www.cnblogs.com/angeldevil/archive/2013/03/10/2952586.html
找到async、sync binder 调用
binder_transaction函数中:
if (reply){
...
}else{
if (!target_node) {
...
}
if(!(tr->flags & TF_ONE_WAY) && target_proc && (proc->pid != target_proc->pid)
获取UID: task_uid(target_proc->tsk).val
判断程序被系统暂停:freezing(task->group_leader) || frozen(task->group_leader)
调用组PID:UID
task_tgid_nr(proc->tsk):task_uid(proc->tsk).val
CF 调度进程判断:
if (task->sched_task_group != NULL) {
struct cfs_bandwidth cfs_b = task->sched_task_group->cfs_bandwidth;
return true;
} else if (cfs_b.quota == -1) {
return false;
}
}
binder_transaction函数中:
if((tr->flags & TF_ONE_WAY) && target_proc && (proc->pid != target_proc->pid){
....
}
off_start_offset = ALIGN(tr->data_size, sizeof(void *));
buffer_offset = off_start_offset;
off_end_offset = off_start_offset + tr->offsets_size;
sg_buf_offset = ALIGN(off_end_offset, sizeof(void *));
sg_buf_end_offset = sg_buf_offset + extra_buffers_size -
ALIGN(secctx_sz, sizeof(u64));
充电、亮灭屏、电话、录屏、窗口改变、应用切换、应用安装/卸载
应用分类:系统应用、三分应用、自研应用、特殊应用(桌面、壁纸、systemUI)
持有锁:定位锁、wakelock、音频锁、jobscheduler、网络数据包、媒体、sync、小部件、通知