Linux 角度看binder原理(四

Linux 角度看binder原理(四)

Service注册

这里使用media服务作为例子。

#frameworks/av/media/mediaserver/main_mediaserver.cpp

#define LOG_TAG "mediaserver"
//#define LOG_NDEBUG 0

#include <binder/IPCThreadState.h>
#include <binder/ProcessState.h>
#include <binder/IServiceManager.h>
#include <hidl/HidlTransportSupport.h>
#include <utils/Log.h>
#include "RegisterExtensions.h"

// from LOCAL_C_INCLUDES
#include "MediaPlayerService.h"
#include "ResourceManagerService.h"

using namespace android;

int main(int argc __unused, char **argv __unused)
{
    signal(SIGPIPE, SIG_IGN);

    sp<ProcessState> proc(ProcessState::self());//获取ProcessState
    sp<IServiceManager> sm(defaultServiceManager());//获取BpServiceManager
    ALOGI("ServiceManager: %p", sm.get());
    MediaPlayerService::instantiate();//注册MediaPlayerService
    ResourceManagerService::instantiate();//注册ResourceManagerService
    registerExtensions();
    ::android::hardware::configureRpcThreadpool(16, false);
    ProcessState::self()->startThreadPool();//开启线程池
    IPCThreadState::self()->joinThreadPool();//将当前线程注册到线程池
    ::android::hardware::joinRpcThreadpool();
}

这里就是大部分服务注册的模板代码了。

  1. 获取ProcessState

  2. 获取BpServiceManager

  3. 注册当前服务

  4. 开启线程池

  5. 将当前线程注册到线程池中

获取BpServiceManager

现在来具体看看这个过程。ProcessState::self() 在上一篇中已经介绍过了会调用init创建一个单例并在创建的时候打开binder驱动调用mmap分配内存,获得binder的能力。接下来是defaultServiceManager()

#frameworks/native/libs/binder/IServiceManager.cpp
using AidlServiceManager = android::os::IServiceManager;
sp<IServiceManager> defaultServiceManager()
{
    std::call_once(gSmOnce, []() {
	..........
        sp<AidlServiceManager> sm = nullptr;
        while (sm == nullptr) {
            sm = interface_cast<AidlServiceManager>(ProcessState::self()->getContextObject(nullptr));
            if (sm == nullptr) {
                ALOGE("Waiting 1s on context object on %s.", ProcessState::self()->getDriverName().c_str());
                sleep(1);
            }
        }

        gDefaultServiceManager = sp<ServiceManagerShim>::make(sm);
    });

    return gDefaultServiceManager;
}

可以看到就是调用了ProcessState::self()->getContextObject(nullptr)拿到了一个某个对象,然后调用interface_cast转为了AidlServiceManager也就是android::os::IServiceManager对象。

#frameworks/native/libs/binder/ProcessState.cpp
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    sp<IBinder> context = getStrongProxyForHandle(0);

    if (context) {
        // The root object is special since we get it directly from the driver, it is never
        // written by Parcell::writeStrongBinder.
        internal::Stability::markCompilationUnit(context.get());
    } else {
        ALOGW("Not able to get context object on %s.", mDriverName.c_str());
    }

    return context;
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;

    AutoMutex _l(mLock);

    if (handle == 0 && the_context_object != nullptr) return the_context_object;//对context_object做了换岑

    handle_entry* e = lookupHandleLocked(handle);

    if (e != nullptr) {

        IBinder* b = e->binder;
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                IPCThreadState* ipc = IPCThreadState::self();
                CallRestriction originalCallRestriction = ipc->getCallRestriction();
                ipc->setCallRestriction(CallRestriction::NONE);
                Parcel data;
                status_t status = ipc->transact(
                        0, IBinder::PING_TRANSACTION, data, nullptr, 0);
                ipc->setCallRestriction(originalCallRestriction);//判断是否是有效的context_object
                if (status == DEAD_OBJECT)
                   return nullptr;
            }

            sp<BpBinder> b = BpBinder::PrivateAccessor::create(handle);//调用的是BpBinder::create(handle)这里handle为null在c++就是0,创建了一个handle为0的Bpbinder。
            e->binder = b.get();
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {

            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}
  class PrivateAccessor {
    private:
        friend class BpBinder;
        friend class ::android::Parcel;
        friend class ::android::ProcessState;
        friend class ::android::RpcSession;
        friend class ::android::RpcState;
        explicit PrivateAccessor(const BpBinder* binder) : mBinder(binder) {}

        static sp<BpBinder> create(int32_t handle) { return BpBinder::create(handle); }
        static sp<BpBinder> create(const sp<RpcSession>& session, uint64_t address) {
            return BpBinder::create(session, address);
        }

        // valid if !isRpcBinder
        int32_t binderHandle() const { return mBinder->binderHandle(); }

        // valid if isRpcBinder
        uint64_t rpcAddress() const { return mBinder->rpcAddress(); }
        const sp<RpcSession>& rpcSession() const { return mBinder->rpcSession(); }

        const BpBinder* mBinder;       
    };

这里可以知道ProcessState::self()->getContextObject(nullptr)拿到的就是一个handle为0的Bpbinder。接下来看interface_cast

#frameworks/native/libs/binder/include/binder/IInterface.h
template<typename INTERFACE>
inline sp<INTERFACE> interface_cast(const sp<IBinder>& obj)
{
    return INTERFACE::asInterface(obj);
}

在很多地方都能看到interface_cast这个方法,它就是一个模板函数调用了asInterface。因为是interface_cast所以就是去android::os::IServiceManager里寻找asInterface方法,这里有一个主要注意的点,在最新的Android12中,Servicemanager已经不是直接和binder驱动交互了,它的实现通过aidl来系统生成代码,这个IServiceManager不是当前frameworks下的这个文件,是通过aidl生成的。在我电脑上编译之后的路径是**/out/soong/.intermediates/frameworks/native/libs/binder/libbinder/android_vendor.31_arm_armv7-a-neon_shared/gen/aidl/android/os**

#IServiceManager.h
class IServiceManager : public ::android::IInterface {
public:
  DECLARE_META_INTERFACE(ServiceManager)
      ........
}
#IServiceManager.cpp
namespace os {
DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager")
}       

      
#define DECLARE_META_INTERFACE(INTERFACE)                                                         \
public:                                                                                           \
    static const ::android::String16 descriptor;                                                  \
    static ::android::sp<I##INTERFACE> asInterface(const ::android::sp<::android::IBinder>& obj); \
    virtual const ::android::String16& getInterfaceDescriptor() const;                            \
    I##INTERFACE();                                                                               \
    virtual ~I##INTERFACE();                                                                      \
    static bool setDefaultImpl(::android::sp<I##INTERFACE> impl);                                 \
    static const ::android::sp<I##INTERFACE>& getDefaultImpl();                                   \
                                                                                                  \
private:                                                                                          \
    static ::android::sp<I##INTERFACE> default_impl;                                              \
    
    
    
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE(INTERFACE, NAME)                        \
    const ::android::StaticString16 I##INTERFACE##_descriptor_static_str16(                     \
            __IINTF_CONCAT(u, NAME));                                                           \
    const ::android::String16 I##INTERFACE::descriptor(I##INTERFACE##_descriptor_static_str16); \
    DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(I##INTERFACE, I##INTERFACE, Bp##INTERFACE)

// Macro to be used by both IMPLEMENT_META_INTERFACE and IMPLEMENT_META_NESTED_INTERFACE
#define DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE0(ITYPE, INAME, BPTYPE)                     \
    const ::android::String16& ITYPE::getInterfaceDescriptor() const { return ITYPE::descriptor; } \
    ::android::sp<ITYPE> ITYPE::asInterface(const ::android::sp<::android::IBinder>& obj) {        \
        ::android::sp<ITYPE> intr;                                                                 \
        if (obj != nullptr) {                                                                      \
            intr = ::android::sp<ITYPE>::cast(obj->queryLocalInterface(ITYPE::descriptor));        \
            if (intr == nullptr) {                                                                 \
                intr = ::android::sp<BPTYPE>::make(obj);                                           \
            }                                                                                      \
        }                                                                                          \
        return intr;                                                                               \
    }                                                                                              \
    ::android::sp<ITYPE> ITYPE::default_impl;                                                      \
    bool ITYPE::setDefaultImpl(::android::sp<ITYPE> impl) {                                        \
        /* Only one user of this interface can use this function     */                            \
        /* at a time. This is a heuristic to detect if two different */                            \
        /* users in the same process use this function.              */                            \
        assert(!ITYPE::default_impl);                                                              \
        if (impl) {                                                                                \
            ITYPE::default_impl = std::move(impl);                                                 \
            return true;                                                                           \
        }                                                                                          \
        return false;                                                                              \
    }                                                                                              \
    const ::android::sp<ITYPE>& ITYPE::getDefaultImpl() { return ITYPE::default_impl; }            \
    ITYPE::INAME() {}                                                                              \
    ITYPE::~INAME() {}

直接寻找是没有asInterface的,它的实现是通过IInterface中的模板方法DECLARE_META_INTERFACEDO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE ,其中DECLARE_META_INTERFACE在头文件中主要就是一个方法的声明,DO_NOT_DIRECTLY_USE_ME_IMPLEMENT_META_INTERFACE在cpp文件中实现方法,在其他服务的实现方式也是同样。把参数(ServiceManager, “android.os.IServiceManager”)带入模板发现就是用android::sp::make(Bpbinder(0))生成了一个BpServiceManager实例。终于拿到了BpServiceManager,回到defaultServiceManager()函数中,最后封装成了一个ServiceManagerShim对象。这里相对于原来的binder框架增加了一个中间层,通过aidl实现一个新的IServiceManager,BpServiceManager增加了一个封装类ServiceManagerShim,功能上没有很大区别。

注册当前服务
void MediaPlayerService::instantiate() {
    defaultServiceManager()->addService(
            String16("media.player"), new MediaPlayerService());
}
//ServiceManagerShim
status_t ServiceManagerShim::addService(const String16& name, const sp<IBinder>& service,
                                        bool allowIsolated, int dumpsysPriority)
{
    Status status = mTheRealServiceManager->addService(
        String8(name).c_str(), service, allowIsolated, dumpsysPriority);
    return status.exceptionCode();
}

就是调用了ServiceManagerShim的addService,而ServiceManagerShim中的所有方法都是调用的BpServiceManager的方法。

//BpServiceManager.addService
    ::android::binder::Status BpServiceManager::addService(const ::std::string& name, const ::android::sp<::android::IBinder>& service, bool allowIsolated, int32_t dumpPriority) {
  ::android::Parcel _aidl_data;
  _aidl_data.markForBinder(remoteStrong());
  ::android::Parcel _aidl_reply;
  ::android::status_t _aidl_ret_status = ::android::OK;
  ::android::binder::Status _aidl_status;
  _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor());
  _aidl_ret_status = _aidl_data.writeUtf8AsUtf16(name);
  _aidl_ret_status = _aidl_data.writeStrongBinder(service);
  _aidl_ret_status = _aidl_data.writeBool(allowIsolated);
  _aidl_ret_status = _aidl_data.writeInt32(dumpPriority);
  _aidl_ret_status = remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0);
    .........
  }

BpServiceManager首先将通讯数据都写入Parcel类型的 _aidl_data变量中,然后调用了BpBinder(0).transact()给binder发送了一个消息。BpBinder实际又是调用了IPCThreadState::self()->transact()

//BpBinder.CPP
status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
  ........
            status = IPCThreadState::self()->transact(binderHandle(), code, data, reply, flags);
    ........
}

//IPCThreadState.CPP

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
 ......
    status_t err;
    flags |= TF_ACCEPT_FDS;
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);//写入
    if (err != NO_ERROR) {
        if (reply) reply->setError(err);
        return (mLastError = err);
    }
    if ((flags & TF_ONE_WAY) == 0) {
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
    } else {
        err = waitForResponse(nullptr, nullptr);
    }
......
    return err;
}

其中就两件事情,一个是writeTransactionData写入数据,一个是waitForResponse发送消息等待数据返回,这里也判断了是否是ONE_WAY,如果是ONE_WAY就调用waitForResponse直接传null返回。

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;

    tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;

    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
        tr.offsets_size = 0;
        tr.data.ptr.offsets = 0;
    } else {
        return (mLastError = err);
    }

    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));

    return NO_ERROR;
}

writeTransactionData其实也没有真正传送数据,它只是将数据写入了mOut中。

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_ACQUIRE_RESULT:
.......
            goto finish;
        case BR_REPLY:
......
            goto finish;
        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }

    return err;
}

可以看到waitForResponse才是真正开启交互的地方,首先通过talkWithDriver与驱动交互,然后通过返回的cmd来处理返回的指令。

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    if (mProcess->mDriverFD < 0) {
        return -EBADF;
    }

    binder_write_read bwr;//传输结构

    const bool needRead = mIn.dataPosition() >= mIn.dataSize();

    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    bwr.write_size = outAvail;
    bwr.write_buffer = (uintptr_t)mOut.data();

    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (uintptr_t)mIn.data();
    } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }

    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 defined(__ANDROID__)
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
#else
        err = INVALID_OPERATION;
#endif
    } while (err == -EINTR);
    ........

    return err;
}

talkWithDriver中做的事情也很简单

  1. 将数据转换成binder_write_read对象
  2. 通过ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)将数据和驱动交互
//binder驱动	
case BC_TRANSACTION_SG:
		case BC_REPLY_SG: {
			struct binder_transaction_data_sg tr;

			if (copy_from_user(&tr, ptr, sizeof(tr)))
				return -EFAULT;
			ptr += sizeof(tr);
			binder_transaction(proc, thread, &tr.transaction_data,
					   cmd == BC_REPLY_SG, tr.buffers_size);
			break;
		}
//binder_transaction()
if (tr->target.handle) {
	
		} else {
			mutex_lock(&context->context_mgr_node_lock);
			target_node = context->binder_context_mgr_node;
			mutex_unlock(&context->context_mgr_node_lock);
		}

binder_transaction中如果handle为0那么直接拿binder_context_mgr_node,这个就是servicemanager注册时候保存的binder_node,通过这个node就能将指令传输给servicemanager。在上一篇中知道servicemanager在注册之后通过BinderCallback来监听客户端的请求。而BinderCallback最终调用了 IPCThreadState::getAndExecuteCommand->IPCThreadState::executeCommand。

status_t IPCThreadState::executeCommand(int32_t cmd)
{
  	.......
    case BR_TRANSACTION_SEC_CTX:
    case BR_TRANSACTION:
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);//BBinder的transact会调用onTransact
    return result;
}

servicemanager的BBinder是通过继承os::BnServiceManager实现的。具体的实现是在IServiceManager。

class BnServiceManager : public ::android::BnInterface<IServiceManager>
    
    
 //IServiceManager.cpp
::android::status_t BnServiceManager::onTransact(uint32_t _aidl_code, const ::android::Parcel& _aidl_data, ::android::Parcel* _aidl_reply, uint32_t _aidl_flags) {
  ::android::status_t _aidl_ret_status = ::android::OK;
  switch (_aidl_code) {
 .........
  case BnServiceManager::TRANSACTION_addService:
  {
    ::std::string in_name;
    ::android::sp<::android::IBinder> in_service;
    bool in_allowIsolated;
    int32_t in_dumpPriority;
    ::android::binder::Status _aidl_status(addService(in_name, in_service, in_allowIsolated, in_dumpPriority));
    _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply);
    if (((_aidl_ret_status) != (::android::OK))) {
      break;
    }
    if (!_aidl_status.isOk()) {
      break;
    }
  }
  break
  }
    

remote()->transact(BnServiceManager::TRANSACTION_addService, _aidl_data, &_aidl_reply, 0)最后又通过ipc回到了ServiceManager.cpp。

//frameworks/native/cmds/servicemanager/ServiceManager.cpp
Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
   
    // implicitly unlinked when the binder is removed
    if (binder->remoteBinder() != nullptr &&
        binder->linkToDeath(sp<ServiceManager>::fromExisting(this)) != OK) {
        LOG(ERROR) << "Could not linkToDeath when adding " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE, "linkToDeath failure");
    }

    // Overwrite the old service if it exists
    mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    };
    auto it = mNameToRegistrationCallback.find(name);
    if (it != mNameToRegistrationCallback.end()) {
        for (const sp<IServiceCallback>& cb : it->second) {
            mNameToService[name].guaranteeClient = true;
            // permission checked in registerForNotifications
            cb->onRegistration(name, binder);
        }
    }
    return Status::ok();
}

用name和binder注册到了mNameToService中。到这里注册就结束了。

ProcessState::self()->startThreadPool() &joinThreadPool()
void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {//保证调用一次
        if (mMaxThreads == 0) {
            ALOGW("Extra binder thread started, but 0 threads requested. Do not use "
                  "*startThreadPool when zero threads are requested.");
        }
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}
void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();//拿到binder线程的名字
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = sp<PoolThread>::make(isMain);//创建一个main PoolThread
        t->run(name.string());
        pthread_mutex_lock(&mThreadCountLock);
        mKernelStartedThreads++;
        pthread_mutex_unlock(&mThreadCountLock);
    }
}
String8 ProcessState::makeBinderThreadName() {
    int32_t s = android_atomic_add(1, &mThreadPoolSeq);
    pid_t pid = getpid();

    std::string_view driverName = mDriverName.c_str();
    android::base::ConsumePrefix(&driverName, "/dev/");

    String8 name;
    name.appendFormat("%.*s:%d_%X", static_cast<int>(driverName.length()), driverName.data(), pid,
                      s);
    return name;
}

startThreadPool保证了只运行一次然后调用了spawnPooledThread,用makeBinderThreadName中获取了Binder线程名,然后创建并运行了一个PoolThread的run方法。

class PoolThread : public Thread
{
public:
    explicit PoolThread(bool isMain)
        : mIsMain(isMain)
    {
    }

protected:
    virtual bool threadLoop()//run实际运行的就是这个方法
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);//这里也是调用了一次joinThreadPool()
        return false;
    }
    const bool mIsMain;
};
void IPCThreadState::joinThreadPool(bool isMain)
{
    LOG_THREADPOOL("**** THREAD %p (PID %d) IS JOINING THE THREAD POOL\n", (void*)pthread_self(), getpid());
    pthread_mutex_lock(&mProcess->mThreadCountLock);
    mProcess->mCurrentThreads++;
    pthread_mutex_unlock(&mProcess->mThreadCountLock);
    mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);//这里为true代表主线程不会超时,不然就是binder驱动生成的线程,将指令写入mOut,main是true就是注册为主线程,false就是驱动请求创建线程

    mIsLooper = true;
    status_t result;
    do {
        processPendingDerefs();
        // now get the next command to be processed, waiting if necessary
        result = getAndExecuteCommand();//和前面讲过的一样触发talkWithDriver,和驱动交互

        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);
        }

        // Let this thread exit the thread pool if it is no longer
        // needed and it is not the main process thread.
        if(result == TIMED_OUT && !isMain) {//如果不是主线程触发超时就会退出
            break;
        }
    } while (result != -ECONNREFUSED && result != -EBADF);

    LOG_THREADPOOL("**** THREAD %p (PID %d) IS LEAVING THE THREAD POOL err=%d\n",
        (void*)pthread_self(), getpid(), result);

    mOut.writeInt32(BC_EXIT_LOOPER);//出了循环就发指令给驱动告诉驱动线程结束了
    mIsLooper = false;
    talkWithDriver(false);
    pthread_mutex_lock(&mProcess->mThreadCountLock);
    LOG_ALWAYS_FATAL_IF(mProcess->mCurrentThreads == 0,
                        "Threadpool thread count = 0. Thread cannot exist and exit in empty "
                        "threadpool\n"
                        "Misconfiguration. Increase threadpool max threads configuration\n");
    mProcess->mCurrentThreads--;
    pthread_mutex_unlock(&mProcess->mThreadCountLock);
}

下面就又进入了驱动层

case BC_REGISTER_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_REGISTER_LOOPER\n",
				     proc->pid, thread->pid);
			binder_inner_proc_lock(proc);
			if (thread->looper & BINDER_LOOPER_STATE_ENTERED) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called after BC_ENTER_LOOPER\n",
					proc->pid, thread->pid);
			} else if (proc->requested_threads == 0) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_REGISTER_LOOPER called without request\n",
					proc->pid, thread->pid);
			} else {
				proc->requested_threads--;//将当前进程的requested_threads减少1
				proc->requested_threads_started++;//将当前进程的requested_threads_started增加1
			}
			thread->looper |= BINDER_LOOPER_STATE_REGISTERED;//将当前线程的looper标志位设置为BINDER_LOOPER_STATE_REGISTERED
			binder_inner_proc_unlock(proc);
			break;
		case BC_ENTER_LOOPER:
			binder_debug(BINDER_DEBUG_THREADS,
				     "%d:%d BC_ENTER_LOOPER\n",
				     proc->pid, thread->pid);
			if (thread->looper & BINDER_LOOPER_STATE_REGISTERED) {
				thread->looper |= BINDER_LOOPER_STATE_INVALID;
				binder_user_error("%d:%d ERROR: BC_ENTER_LOOPER called after BC_REGISTER_LOOPER\n",
					proc->pid, thread->pid);
			}
			thread->looper |= BINDER_LOOPER_STATE_ENTERED;//将当前线程的looper标志位设置为BINDER_LOOPER_STATE_ENTERED
			break;

如果命令是BC_ENTER_LOOPER的话只是线程的标志位改了并不会去修改线程池中的变量。通过joinThreadPool(true)注册的线程都是不占用线程池的线程数量的。joinThreadPool方法的默认值是true所以在mediaserver中注册了两个线程到了线程池中,到这里mediaserver也就启动结束了。

binder驱动创建线程

创建完线程池之后主线程会一直通过talkWithDriver与binder驱动交互,当有任务时候会通过binder_thread_read来处理。

static int binder_thread_read(struct binder_proc *proc,
			      struct binder_thread *thread,
			      binder_uintptr_t binder_buffer, size_t size,
			      binder_size_t *consumed, int non_block)
{
........
retry:
	binder_inner_proc_lock(proc);
	wait_for_proc_work = binder_available_for_proc_work_ilocked(thread);//检查thread的todo队列中是否有待处理的work,如果没有那就等待处理本进程todo队列的work
	binder_inner_proc_unlock(proc);

	thread->looper |= BINDER_LOOPER_STATE_WAITING;

	if (non_block) {
		if (!binder_has_work(thread, wait_for_proc_work))
			ret = -EAGAIN;
	} else {
		ret = binder_wait_for_work(thread, wait_for_proc_work);//没有数据就进入等待直到有数据被唤醒
	}

	thread->looper &= ~BINDER_LOOPER_STATE_WAITING;

	if (ret)
		return ret;

	while (1) {
		uint32_t cmd;
		struct binder_transaction_data_secctx tr;
		struct binder_transaction_data *trd = &tr.transaction_data;
		struct binder_work *w = NULL;
		struct list_head *list = NULL;
		struct binder_transaction *t = NULL;
		struct binder_thread *t_from;
		size_t trsize = sizeof(*trd);

		binder_inner_proc_lock(proc);
		if (!binder_worklist_empty_ilocked(&thread->todo))
			list = &thread->todo;//读取线程队列
		else if (!binder_worklist_empty_ilocked(&proc->todo) &&
			   wait_for_proc_work)
			list = &proc->todo;//读取进程队列
		else {
			binder_inner_proc_unlock(proc);

			/* no data added */
			if (ptr - buffer == 4 && !thread->looper_need_return)
				goto retry;//如果没数据就循环
			break;
		}

		if (end - ptr < sizeof(tr) + 4) {
			binder_inner_proc_unlock(proc);
			break;
		}
		w = binder_dequeue_work_head_ilocked(list);//拿到事务
		switch (w->type) {//根据类型处理事务
                ........
		case BINDER_WORK_TRANSACTION: {
			binder_inner_proc_unlock(proc);
			t = container_of(w, struct binder_transaction, work);
		} break;
         case BINDER_WORK_DEAD_BINDER:
		case BINDER_WORK_DEAD_BINDER_AND_CLEAR:
		case BINDER_WORK_CLEAR_DEATH_NOTIFICATION: {
			struct binder_ref_death *death;
			uint32_t cmd;
			binder_uintptr_t cookie;
			.......
			death = container_of(w, struct binder_ref_death, work);
			if (w->type == BINDER_WORK_CLEAR_DEATH_NOTIFICATION)
				cmd = BR_CLEAR_DEATH_NOTIFICATION_DONE;
			else
				cmd = BR_DEAD_BINDER;
            .......
			if (cmd == BR_DEAD_BINDER)
				goto done; /* DEAD_BINDER notifications can cause transactions */
		} break;
		}

		if (!t)//只有BINDER_WORK_TRANSACTION命令才能继续往下执行
			continue;
.......
done:

	*consumed = ptr - buffer;
	binder_inner_proc_lock(proc);
	if (proc->requested_threads == 0 &&
	    list_empty(&thread->proc->waiting_threads) &&
	    proc->requested_threads_started < proc->max_threads &&
	    (thread->looper & (BINDER_LOOPER_STATE_REGISTERED |
	     BINDER_LOOPER_STATE_ENTERED)) /* the user-space code fails to */
	     /*spawn a new thread if we leave this out */) {//判断是否新增线程
		proc->requested_threads++;
		binder_inner_proc_unlock(proc);
		binder_debug(BINDER_DEBUG_THREADS,
			     "%d:%d BR_SPAWN_LOOPER\n",
			     proc->pid, thread->pid);
		if (put_user(BR_SPAWN_LOOPER, (uint32_t __user *)buffer))//发送BR_SPAWN_LOOPER
			return -EFAULT;
		binder_stat_br(proc, thread, BR_SPAWN_LOOPER);
	} else
		binder_inner_proc_unlock(proc);
	return 0;
}

在done中创建新线程,触发done的只有BINDER_WORK_TRANSACTION和发送死亡通知的时候。done中创建线程有下面几个条件

  1. 当前进程的requested_threads 为0,就是没申请创建。
  2. 可以线程waiting_threads 为0
  3. requested_threads_started运行线程小于最大线程值,这里就发现通过BC_ENTER_LOOPER进入线程池的线程不在这个范围里。
  4. 当前线程是BINDER_LOOPER_STATE_REGISTERED或者BINDER_LOOPER_STATE_ENTERED的,就是通过joinThreadPool加入的,这个条件不知道什么时候会不满足。

当都满足之后会增加proc->requested_threads++;并且将BR_SPAWN_LOOPER发送回用户空间。

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);
        break;
    }
    return result;
}

又回到了spawnPooledThread中,通过传入isMain为false来创建了一个普通的线程。这样Binder线程管理部分就闭环了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Binder通信原理是Android中一种跨进程通信机制。它通过Binder驱动和Binder服务来实现进程间的通信。具体实现方式可以参考。 在Binder通信原理中,有三个关键的组件:Binder驱动、Binder服务和Binder客户端。Binder驱动是操作系统提供的内核模块,它负责在进程间传递消息。而Binder服务是一个独立的进程,用于管理和提供跨进程通信的能力。Binder客户端则是调用Binder服务的进程。 在通信过程中,首先需要调用binder_open函数打开Binder设备,然后使用mmap函数进行内存映射,将用户空间的内存映射到内核空间。接下来,通过ioctl函数进行实际的通信操作。 Android中的四大组件(Activity、Service、BroadcastReceiver和ContentProvider)的启动原理也与Binder IPC机制有关。其中,ActivityManagerService、PackageManagerService、WindowManagerService、PowerManagerService等服务的调用也与Binder IPC机制有关。 综上所述,Binder通信原理是Android中一种跨进程通信机制,通过Binder驱动和Binder服务来实现进程间的通信。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [Binder通信机制原理解析](https://blog.csdn.net/Awenyini/article/details/78806893)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Binder通信原理](https://blog.csdn.net/z1804362542/article/details/127959348)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值