分享

binder 源码集锦

 开花结果 2022-06-14 发布于北京

目录

                                                                         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

https://blog.csdn.net/nihaomabmt/article/details/116784540

https://blog.csdn.net/nihaomabmt/article/details/116784540

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多