目录 binder c ServiceManager Servicemanager 接口及实现 Servicemanager 启动 Binder c 一些重要数据结构对象 ProcessState和PCThreadState binder_proc和binder_thread binder_node和binder_ref binder_transaction和binder_work binder_alloc和binder_buffer android Binder 线程创建 binder驱动简述 addService 流程分析 defaultServiceManager()流程分析 addService BpBinder.transact->IPCThreadState.transact waitForResponse->talkWithDriver talkWithDriver->ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) Ioctl->binder_ioctl_write_read BC_TRANSACTION->binder_transaction 服务端binder_thread_read 发起端binder_thread_read BR_TRANSACTION->BBinder->transact BR_TRANSACTION->sendReply getService流程 IPCThreadState既作为客户端,又作为服务端 作为客户端(发起端) 作为服务端 参考链接 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 https://skytoby./2020/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3Binder%E6%9C%BA%E5%88%B65-binder%E9%A9%B1%E5%8A%A8%E5%88%86%E6%9E%90/ 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 binder_transaction 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 Mutex类使用Futex实现同步 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; if (cfs_b.quota != -1) { 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、小部件、通知 ———————————————— 版权声明:本文为CSDN博主「lei7143」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lei7143/article/details/112480855 https://blog.csdn.net/jasonactions/article/details/119732367 https://blog.csdn.net/jasonactions/article/details/119732367 https://blog.csdn.net/jasonactions/article/details/119736519 |
|