Android Binder通信原理(二):servicemanager启动

这篇具有很好参考价值的文章主要介绍了Android Binder通信原理(二):servicemanager启动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

源码基于:Android R

0. 前言

下图是android 8.0 之前binder 的软件框架,依赖的驱动设备是/dev/binder,binder机制的四要素分别是client、server、servicemanager和binder驱动。

对于android 8.0后的binder 和vndbinder依然同这个框架,只不过驱动的设备多加/dev/vndbinder

Android Binder通信原理(二):servicemanager启动

这篇主要分析servicemanger的流程,hwservicemanger后续补充。

2. servicemanager 生成

先来看下该bin 文件产生:

frameworks/native/cmds/servicemanager/Android.bp

cc_binary {
    name: "servicemanager",
    defaults: ["servicemanager_defaults"],
    init_rc: ["servicemanager.rc"],
    srcs: ["main.cpp"],
}

cc_binary {
    name: "vndservicemanager",
    defaults: ["servicemanager_defaults"],
    init_rc: ["vndservicemanager.rc"],
    vendor: true,
    cflags: [
        "-DVENDORSERVICEMANAGER=1",
    ],
    srcs: ["main.cpp"],
}

该目录下通过同样的main.cpp 编译出两个bin 文件:servicemanager 和 vndservicemanager,两个bin 文件对应不同的 *.rc 文件。

frameworks/native/cmds/servicemanager/servicemanager.rc

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver
    onrestart restart keystore
    onrestart restart gatekeeperd
    onrestart restart thermalservice
    writepid /dev/cpuset/system-background/tasks
    shutdown critical
frameworks/native/cmds/servicemanager/vndservicemanager.rc

service vndservicemanager /vendor/bin/vndservicemanager /dev/vndbinder
    class core
    user system
    group system readproc
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

3. servicemanager 的main()

frameworks/native/cmds/servicemanager/main.cpp

int main(int argc, char** argv) {
    if (argc > 2) {
        LOG(FATAL) << "usage: " << argv[0] << " [binder driver]";
    }

    //根据参数确认代码的设备是binder还是vndbinder
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";

    //驱动设备的初始化工作,后面第 3.1 节详细说明
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);

    //告知驱动最大线程数,并设定servicemanger的线程最大数
    ps->setThreadPoolMaxThreadCount(0);
    //调用处理,以error方式还是fatal
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);

    //核心的接口都在这里
    sp<ServiceManager> manager = new ServiceManager(std::make_unique<Access>());

    //将servicemanager作为一个特殊service添加进来
    if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
        LOG(ERROR) << "Could not self register servicemanager";
    }

    //保存进程的context obj
    IPCThreadState::self()->setTheContextObject(manager);
    //通知驱动context mgr是该context
    ps->becomeContextManager(nullptr, nullptr);

    //servicemanager 中新建一个looper,用以处理binder消息
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);

    //通知驱动进入looper,并开始监听驱动消息,并设立callback进行处理
    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);

    //启动looper,进入每次的poll处理,进程如果没有出现异常情况导致abort是不会退出的
    while(true) {
        looper->pollAll(-1);
    }

    // should not be reached
    return EXIT_FAILURE;
}

3.1 initWithDriver()

frameworks/native/libs/binder/ProcessState.cpp

sp<ProcessState> ProcessState::initWithDriver(const char* driver)
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        // Allow for initWithDriver to be called repeatedly with the same
        // driver.
        if (!strcmp(gProcess->getDriverName().c_str(), driver)) {
            return gProcess;
        }
        LOG_ALWAYS_FATAL("ProcessState was already initialized.");
    }

    if (access(driver, R_OK) == -1) {
        ALOGE("Binder driver %s is unavailable. Using /dev/binder instead.", driver);
        driver = "/dev/binder";
    }

    gProcess = new ProcessState(driver);
    return gProcess;
}

函数的参数为driver 的设备名称,是 /dev/binder 还是 /dev/vndbinder。

另外的逻辑比较简单,ProcesState 是管理 “进程状态”,Binder 中每个进程都会有且只有一个mProcess 对象,如果该实例不为空,则确认该实例打开的driver 是否为当前需要init 的driver 名称;如果该实例不存在,则通过 new 创建一个。

详细的PorcessState 可以查看第 4 节。

3.2 new ServiceManager()

核心的接口都是位于Servicemanager 中,这里构造时新建一个Access 对象,如下:

frameworks/native/cmds/servicemanager/ServiceManager.cpp

ServiceManager::ServiceManager(std::unique_ptr<Access>&& access) : mAccess(std::move(access)) {
    ...
}

通过move 接口调用 Access 的移动构造函数,创建实例mAccess,mAccess 用于通过selinux 确认servicemanager的权限。

3.3 addService()

if (!manager->addService("manager", manager, false /*allowIsolated*/, IServiceManager::DUMP_FLAG_PRIORITY_DEFAULT).isOk()) {
    LOG(ERROR) << "Could not self register servicemanager";
}

如果是其他的service 注册到servicemanager 是需要通过 IServiceManager 经过binder 最终调用到ServiceManager 中的addService(),而这里直接通过 ServiceManager 对象直接注册。

frameworks/native/cmds/servicemanager/ServiceManager.cpp

Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    auto ctx = mAccess->getCallingContext();

    //应用进程没有权限注册服务
    if (multiuser_get_app_id(ctx.uid) >= AID_APP) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    // selinux 曲线是否允许注册为SELABEL_CTX_ANDROID_SERVICE
    if (!mAccess->canAdd(ctx, name)) {
        return Status::fromExceptionCode(Status::EX_SECURITY);
    }

    //传入的IBinder 不能为nullptr
    if (binder == nullptr) {
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

    //service name 需要符合要求,由0-9、a-z、A-Z、下划线、短线、点号、斜杠组成,name 长度不能超过127
    if (!isValidServiceName(name)) {
        LOG(ERROR) << "Invalid service name: " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }

    //这里应该是需要普通的vnd service 进行vintf 声明
#ifndef VENDORSERVICEMANAGER
    if (!meetsDeclarationRequirements(binder, name)) {
        // already logged
        return Status::fromExceptionCode(Status::EX_ILLEGAL_ARGUMENT);
    }
#endif  // !VENDORSERVICEMANAGER

    //注册linkToDeath,监听service 状态
    if (binder->remoteBinder() != nullptr && binder->linkToDeath(this) != OK) {
        LOG(ERROR) << "Could not linkToDeath when adding " << name;
        return Status::fromExceptionCode(Status::EX_ILLEGAL_STATE);
    }

    //添加到map 中
    auto entry = mNameToService.emplace(name, Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority,
        .debugPid = ctx.debugPid,
    });

    //确认是否注册了service callback,如果注册调用回调
    auto it = mNameToRegistrationCallback.find(name);
    if (it != mNameToRegistrationCallback.end()) {
        for (const sp<IServiceCallback>& cb : it->second) {
            entry.first->second.guaranteeClient = true;
            // permission checked in registerForNotifications
            cb->onRegistration(name, binder);
        }
    }

    return Status::ok();
}

3.4 setTheContextObject()

    IPCThreadState::self()->setTheContextObject(manager);
    ps->becomeContextManager(nullptr, nullptr);

第一行是创建 IPCThreadState,并将 servicemanager 存放到IPCThreadState 中,用于后面transact 使用。

第二行通过命令 BINDER_SET_CONTEXT_MGR_EXT 通知驱动 context mgr:

frameworks/native/libs/binder/ProcessState.cpp

bool ProcessState::becomeContextManager(context_check_func checkFunc, void* userData)
{
    AutoMutex _l(mLock);
    mBinderContextCheckFunc = checkFunc;
    mBinderContextUserData = userData;

    flat_binder_object obj {
        .flags = FLAT_BINDER_FLAG_TXN_SECURITY_CTX,
    };

    int result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR_EXT, &obj);

    // fallback to original method
    if (result != 0) {
        android_errorWriteLog(0x534e4554, "121035042");

        int dummy = 0;
        result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &dummy);
    }

    if (result == -1) {
        mBinderContextCheckFunc = nullptr;
        mBinderContextUserData = nullptr;
        ALOGE("Binder ioctl to become context manager failed: %s\n", strerror(errno));
    }

    return result == 0;
}

通知驱动创建context_mgr_node,下面是驱动层的代码:

drivers/android/binder.c

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    ...
	case BINDER_SET_CONTEXT_MGR_EXT: {
        struct flat_binder_object fbo;
        
        if (copy_from_user(&fbo, ubuf, sizeof(fbo))) {
        ret = -EINVAL;
        goto err;
        }
        ret = binder_ioctl_set_ctx_mgr(filp, &fbo);
        if (ret)
        goto err;
        break;
	}
	case BINDER_SET_CONTEXT_MGR:
        ret = binder_ioctl_set_ctx_mgr(filp, NULL);
        if (ret)
        goto err;
        break;
    ...
    ...
}

两个cmd 主要区别是否有flat_binder_object,最终都是调用binder_ioctl_set_ctx_mgr 函数:

drivers/android/binder.c

static int binder_ioctl_set_ctx_mgr(struct file *filp,
				    struct flat_binder_object *fbo)
{
	int ret = 0;
    //进程的binder_proc, 这里是ServiceManager的 binder_proc,之前通过open("/dev/binder")得来
	struct binder_proc *proc = filp->private_data;
	struct binder_context *context = proc->context;
	struct binder_node *new_node;
	kuid_t curr_euid = current_euid();   // 线程的uid

	mutex_lock(&context->context_mgr_node_lock);
    //正常第一次为null,如果不为null则说明该进程已经设置过context mgr则直接退出
	if (context->binder_context_mgr_node) {
        pr_err("BINDER_SET_CONTEXT_MGR already set\n");
        ret = -EBUSY;
        goto out;
	}

    //检查当前进程是否具有注册Context Manager的SEAndroid安全权限
	ret = security_binder_set_context_mgr(proc->tsk);
	if (ret < 0)
		goto out;
	if (uid_valid(context->binder_context_mgr_uid)) {
        //读取binder_context_mgr_uid和当前的比,如果不一样,报错
        if (!uid_eq(context->binder_context_mgr_uid, curr_euid)) {
        pr_err("BINDER_SET_CONTEXT_MGR bad uid %d != %d\n",
              from_kuid(&init_user_ns, curr_euid),
              from_kuid(&init_user_ns,
        	 context->binder_context_mgr_uid));
        ret = -EPERM;
        goto out;
        }
	} else {
	    context->binder_context_mgr_uid = curr_euid;
	}

    //创建binder_node对象
	new_node = binder_new_node(proc, fbo);
	if (!new_node) {
        ret = -ENOMEM;
        goto out;
	}
	binder_node_lock(new_node);
	new_node->local_weak_refs++;
	new_node->local_strong_refs++;
	new_node->has_strong_ref = 1;
	new_node->has_weak_ref = 1;
    //把新创建的node对象赋值给context->binder_context_mgr_node,成为serviceManager的binder管理实体
	context->binder_context_mgr_node = new_node;
	binder_node_unlock(new_node);
	binder_put_node(new_node);
out:
	mutex_unlock(&context->context_mgr_node_lock);
	return ret;
}

binder_ioctl_set_ctx_mgr()的流程也比较简单

  • 先检查当前进程是否具有注册Context Manager的SEAndroid安全权限
  • 如果具有SELinux权限,会为整个系统的上下文管理器专门生成一个binder_node节点,使该节点的强弱应用加1
  • 新创建的binder_node 节点,记入context->binder_context_mgr_node,即ServiceManager 进程的context binder节点,使之成为serviceManager的binder管理实体

3.5 Looper::prepare()

sp<Looper> looper = Looper::prepare(0 /* opts */);

详细代码不列出来,主要是通过 epoll 方式添加对 fd 的监听

3.6 BinderCallback::setupTo(looper)

frameworks/native/cmds/servicemanager/main.cpp

class BinderCallback : public LooperCallback {
public:
    static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
        sp<BinderCallback> cb = new BinderCallback;

        int binder_fd = -1;
        //获取主线程的binder fd,并通知驱动ENTER_LOOPER
        IPCThreadState::self()->setupPolling(&binder_fd);
        LOG_ALWAYS_FATAL_IF(binder_fd < 0, "Failed to setupPolling: %d", binder_fd);

        //将线程中的cmd flush 给驱动,此处应该是ENTER_LOOPER
        IPCThreadState::self()->flushCommands();

        //looper 中的epoll 添加对binder_fd 的监听,并且将callback 注册进去,会回调handleEvent
        int ret = looper->addFd(binder_fd,
                                Looper::POLL_CALLBACK,
                                Looper::EVENT_INPUT,
                                cb,
                                nullptr /*data*/);
        LOG_ALWAYS_FATAL_IF(ret != 1, "Failed to add binder FD to Looper");

        return cb;
    }

    //epoll 触发该fd事件时,会回调该函数
    int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
        IPCThreadState::self()->handlePolledCommands();
        return 1;  // Continue receiving callbacks.
    }
};

其实,每一个普通的service 在创建后,都会调用 ProcessState::startThreadPool() 产生一个main IPC thread,进而用其通过 IPCThreadState::joinThreadPool() 卵生其他的 IPCThreadState,但是 servicemanager 因为不需要其他线程,所以只是在主线程中使用Looper进行进一步的监听。

每一个IPCThreadState 核心应该就是监听、处理 binder 驱动的交互信息,而这些操作都是在函数getAndExecuteCommand() 中,详细看第 5.4 节。

3.7 ClientCallbackCallback::setupTo(looper, manager)

这里具体不清楚是为什么,从代码上看是ServiceManager 在addService之前可以选择先registerClientCallback,这样如果 addService() 成功会回调通知。

至于这里ClientCallbackCallback,设定了定时器,5s 触发一次,感觉是个心跳包。

3.8 looper->pollAll(-1)

进入无限循环

4. ProcessState 类

ProcesState 是管理 “进程状态”,Binder 中每个进程都会有且只有一个mProcess 对象。该对象用以:

  • 初始化驱动设备;
  • 记录驱动的名称、FD;
  • 记录进程线程数量的上限;
  • 记录binder 的 context obj;
  • 启动 binder线程;

4.1 ProcessState 构造

frameworks/native/libs/binder/ProcessState.cpp

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))
    , mVMStart(MAP_FAILED)
    , mThreadCountLock(PTHREAD_MUTEX_INITIALIZER)
    , mThreadCountDecrement(PTHREAD_COND_INITIALIZER)
    , mExecutingThreadsCount(0)
    , mMaxThreads(DEFAULT_MAX_BINDER_THREADS)
    , mStarvationStartTimeMs(0)
    , mBinderContextCheckFunc(nullptr)
    , mBinderContextUserData(nullptr)
    , mThreadPoolStarted(false)
    , mThreadPoolSeq(1)
    , mCallRestriction(CallRestriction::NONE)
{

// TODO(b/139016109): enforce in build system
#if defined(__ANDROID_APEX__)
    LOG_ALWAYS_FATAL("Cannot use libbinder in APEX (only system.img libbinder) since it is not stable.");
#endif

    if (mDriverFD >= 0) {
        // mmap the binder, providing a chunk of virtual address space to receive transactions.
        mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
        if (mVMStart == MAP_FAILED) {
            // *sigh*
            ALOGE("Using %s failed: unable to mmap transaction memory.\n", mDriverName.c_str());
            close(mDriverFD);
            mDriverFD = -1;
            mDriverName.clear();
        }
    }

#ifdef __ANDROID__
    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver '%s' could not be opened.  Terminating.", driver);
#endif
}

该函数主要做了如下:

在初始化列表中,通过调用 open_driver() 代码设备驱动,详见后面第 4.3 节;

如果驱动open 成功,mDriverFD 被赋值后,通过mmap() 创建大小 BINDER_VM_SIZE 的buffer,用以接收 transactions 数据。

通过命令行可以确认这个大小,假设 servicemanager 的PID 为510,则通过:

cat /proc/510/maps 可以看到:

748c323000-748c421000 r--p 00000000 00:1f 4                              /dev/binderfs/binder

不用奇怪为什么不是/dev/binder,软连接而已:

lrwxrwxrwx  1 root      root                  20 1970-01-01 05:43 binder -> /dev/binderfs/binder
lrwxrwxrwx  1 root      root                  22 1970-01-01 05:43 hwbinder -> /dev/binderfs/hwbinder
lrwxrwxrwx  1 root      root                  22 1970-01-01 05:43 vndbinder -> /dev/binderfs/vndbinder

4.2 ProcessState 单例

ProcessState 使用self() 函数获取对象,因为有 vndbinder 和binder共用一份代码,所以如果需要使用 vndbinder,需要在调用 self() 函数前调用 initWithDriver() 来指定驱动设备名称。当然如果强制使用self() 函数,那么获取的单例针对的驱动设备为 kDefaultDriver

frameworks/native/libs/binder/ProcessState.cpp

#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
const char* kDefaultDriver = "/dev/binder";
#endif

sp<ProcessState> ProcessState::self()
{
    Mutex::Autolock _l(gProcessMutex);
    if (gProcess != nullptr) {
        return gProcess;
    }
    gProcess = new ProcessState(kDefaultDriver);
    return gProcess;
}

4.3 open_driver()

对于 binder 和 vndbinder 设备,在 ProcessState 构造的时候会在初始化列表中调用 open_driver() 来对设备进行 open 和初始化。

frameworks/native/libs/binder/ProcessState.cpp

static int open_driver(const char *driver)
{
    //通过系统调用open 设备
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;

        //如果open 成功,会查询binder version是否匹配
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
        if (result == -1) {
            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));
            close(fd);
            fd = -1;
        }

        //如果不是当前的version,为什么还是不return?
        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {
          ALOGE("Binder driver protocol(%d) does not match user space protocol(%d)! ioctl() return value: %d",
                vers, BINDER_CURRENT_PROTOCOL_VERSION, result);
            close(fd);
            fd = -1;
        }
        size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
        //如果binder version 是当前的,会通知驱动设置最大的线程数
        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
        if (result == -1) {
            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));
        }
    } else {
        ALOGW("Opening '%s' failed: %s\n", driver, strerror(errno));
    }
    return fd;
}

这里需要注意,每个进程创建的 binder 的最大线程数为:DEFAULT_MAX_BINDER_THREADS

frameworks/native/libs/binder/ProcessState.cpp

#define DEFAULT_MAX_BINDER_THREADS 15

对于servicemanager,main 函数中设定为 0,也就是servicemanager 直接使用主线程,普通service 限制最大的binder thread为 15,详细在后面进行驱动分析。

这里补充一下,在system_server 进程中,binder 的数量最大值为 31

frameworks/base/services/java/com/android/server/SystemServer.java

    private static final int sMaxBinderThreads = 31;

    private void run() {
            ...
            BinderInternal.setMaxThreads(sMaxBinderThreads);
            ...
    }

4.4 makeBinderThreadName()

frameworks/native/libs/binder/ProcessState.cpp

String8 ProcessState::makeBinderThreadName() {
    int32_t s = android_atomic_add(1, &mThreadPoolSeq);
    pid_t pid = getpid();
    String8 name;
    name.appendFormat("Binder:%d_%X", pid, s);
    return name;
}

这是产生binder 线程名称的函数,通过变量 mThreadPoolSeq 控制顺序和个数,最终的binder 线程名称类似 Binder:1234_F

线程的最大数量是规定的,如上一些中说到的 DEFAULT_MAX_BINDER_THREADS (默认为15)。

当然,也可以通过 setThreadPoolMaxThreadCount() 函数来设定最大线程数,在servicemanager 中就是通过该函数指定 max threads为0,详细见第 3 节。

4.4.1 setThreadPoolMaxThreadCount()

frameworks/native/libs/binder/ProcessState.cpp

status_t ProcessState::setThreadPoolMaxThreadCount(size_t maxThreads) {
    status_t result = NO_ERROR;
    if (ioctl(mDriverFD, BINDER_SET_MAX_THREADS, &maxThreads) != -1) {
        mMaxThreads = maxThreads;
    } else {
        result = -errno;
        ALOGE("Binder ioctl to set max threads failed: %s", strerror(-result));
    }
    return result;
}

在第 4.3 节的时候已经说明过,当 ProcessState 构造时会open_driver(),此处会将默认的 binder thread 最大值通知给 binder 驱动。默认binder thread 的MAX 值为 15。

进程可以通过 ProcessState 单独设定binder thread 的MAX 值,例如,system_server 进程就将该值设为 31,servicemanager 进程将该值设为0.

4.5 startThreadPool()

frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::startThreadPool()
{
    AutoMutex _l(mLock);
    if (!mThreadPoolStarted) {
        mThreadPoolStarted = true;
        spawnPooledThread(true);
    }
}

每个binder 通信的进程,都需要调用该函数。

该函数可以说是binder 通信的开端和必然流程。原因大概有两个:

  • 每个进程的 binder 通信都会保存一个 ProcessState 单例,都会有个状态保护,也就是这里 mThreadPoolStarted 变量,后面任何binder 线程卵生都需要调用 spawnPooledThread(),而这个函数前提条件是 mThreadPoolStarted 为true;
  • 对于 binder 驱动而言,每个进程都需要创建一个 主 binder 线程,其他binder 线程都是非主线程;

4.6 spawnPooledThread()

frameworks/native/libs/binder/ProcessState.cpp

void ProcessState::spawnPooledThread(bool isMain)
{
    if (mThreadPoolStarted) {
        String8 name = makeBinderThreadName();
        ALOGV("Spawning new pooled thread, name=%s\n", name.string());
        sp<Thread> t = new PoolThread(isMain);
        t->run(name.string());
    }
}

这个用来卵生新的 binder thread,PoolThread 继承自Thread,run 的时候会将 binder name 带入,所以,在打印线程堆栈时能知道第几个Binder 的线程。而每一个binder thread 都会通过IPCThreadState 管理:

frameworks/native/libs/binder/ProcessState.cpp

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

protected:
    virtual bool threadLoop()
    {
        IPCThreadState::self()->joinThreadPool(mIsMain);
        return false;
    }

    const bool mIsMain;
};

5. IPCThreadState 类

同 ProcessState 类,每个进程有很多的线程用来记录 “线程状态”,在每次binder 的BINDER_WRITE_READ 调用后,驱动都会根据情况确定是否需要spawn 线程,而创建一个PoolThread(详见ProcessState) 都会伴随一个IPCThreadState进行管理,而binder 线程中所有的操作都是通过 IPCThreadState 进行的。

5.1 IPCThreadState 构造

frameworks/native/libs/binder/IPCThreadState.cpp

IPCThreadState::IPCThreadState()
    : mProcess(ProcessState::self()),
      mServingStackPointer(nullptr),
      mWorkSource(kUnsetWorkSource),
      mPropagateWorkSource(false),
      mStrictModePolicy(0),
      mLastTransactionBinderFlags(0),
      mCallRestriction(mProcess->mCallRestriction)
{
    pthread_setspecific(gTLS, this);
    clearCaller();
    mIn.setDataCapacity(256);
    mOut.setDataCapacity(256);
}

5.2 self()

frameworks/native/libs/binder/IPCThreadState.cpp

IPCThreadState* IPCThreadState::self()
{
    if (gHaveTLS.load(std::memory_order_acquire)) {
restart:
        const pthread_key_t k = gTLS;
        IPCThreadState* st = (IPCThreadState*)pthread_getspecific(k);
        if (st) return st;
        return new IPCThreadState;
    }

    // Racey, heuristic test for simultaneous shutdown.
    if (gShutdown.load(std::memory_order_relaxed)) {
        ALOGW("Calling IPCThreadState::self() during shutdown is dangerous, expect a crash.\n");
        return nullptr;
    }

    pthread_mutex_lock(&gTLSMutex);
    if (!gHaveTLS.load(std::memory_order_relaxed)) {
        int key_create_value = pthread_key_create(&gTLS, threadDestructor);
        if (key_create_value != 0) {
            pthread_mutex_unlock(&gTLSMutex);
            ALOGW("IPCThreadState::self() unable to create TLS key, expect a crash: %s\n",
                    strerror(key_create_value));
            return nullptr;
        }
        gHaveTLS.store(true, std::memory_order_release);
    }
    pthread_mutex_unlock(&gTLSMutex);
    goto restart;
}

每个线程创建后,都会通过pthread_getspecific() 确认TLS中是否有已经创建了IPCThreadState,如果有就直接返回,如果没有则新建一个。

5.3 setupPolling()

frameworks/native/libs/binder/IPCThreadState.cpp

int IPCThreadState::setupPolling(int* fd)
{
    if (mProcess->mDriverFD < 0) {
        return -EBADF;
    }

    mOut.writeInt32(BC_ENTER_LOOPER);
    *fd = mProcess->mDriverFD;
    return 0;
}

主要做两件事情,发送 BC_ENTER_LOOPER 通知驱动进入looper,并将驱动 fd 返回。

5.4 getAndExecuteCommand()

frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::getAndExecuteCommand()
{
    status_t result;
    int32_t cmd;

    //step1,与binder驱动交互,等待binder驱动返回
    result = talkWithDriver();
    if (result >= NO_ERROR) {
        size_t IN = mIn.dataAvail();
        if (IN < sizeof(int32_t)) return result;

        //step2,解析从binder驱动中的reply command
        cmd = mIn.readInt32();

        //step3,留意binder处理的thread count
        //system server中会喂狗,这里当处理的线程count超过最大值,monitor会阻塞直到有足够的数量
        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount++;
        if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs == 0) {
            mProcess->mStarvationStartTimeMs = uptimeMillis();
        }
        pthread_mutex_unlock(&mProcess->mThreadCountLock);

        //step4,binder通信用户端的核心处理函数,根据reply command进行对应的处理
        result = executeCommand(cmd);

        //step5,每个线程executeCommand() 完成都会将thread count减1,且每次都会条件变量broadcast
        pthread_mutex_lock(&mProcess->mThreadCountLock);
        mProcess->mExecutingThreadsCount--;
        if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&
                mProcess->mStarvationStartTimeMs != 0) {
            int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;
            if (starvationTimeMs > 100) {
                ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",
                      mProcess->mMaxThreads, starvationTimeMs);
            }
            mProcess->mStarvationStartTimeMs = 0;
        }
        pthread_cond_broadcast(&mProcess->mThreadCountDecrement);
        pthread_mutex_unlock(&mProcess->mThreadCountLock);
    }

    return result;
}

代码逻辑上还是比较简单,主要是三部分:

  • talkWithDriver() 与binder 驱动交互,并确定返回值是否异常;
  • 确定execute thread count,system server会喂狗;
  • executeCommand() 进行核心处理;

重点的两个函数处理逻辑比较复杂,下面先简单分析下。

5.4.1 talkWithDriver()

frameworks/native/libs/binder/IPCThreadState.cpp

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

    binder_write_read bwr;

    // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();

    // We don't want to write anything if we are still reading
    // from data left in the input buffer and the caller
    // has requested to read the next data.
    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

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

    // 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;

        if (mProcess->mDriverFD < 0) {
            err = -EBADF;
        }
    } while (err == -EINTR);

    if (err >= NO_ERROR) {
        if (bwr.write_consumed > 0) {
            if (bwr.write_consumed < mOut.dataSize())
                LOG_ALWAYS_FATAL(...);
            else {
                mOut.setDataSize(0);
                processPostWriteDerefs();
            }
        }
        if (bwr.read_consumed > 0) {
            mIn.setDataSize(bwr.read_consumed);
            mIn.setDataPosition(0);
        }

        return NO_ERROR;
    }

    return err;
}

IPCThreadState 中存放了两个信息:mIn mOutmIn 是用来read驱动的数据,mOut 是用来write 驱动的数据。

这里核心是do...while循环,通过命令 BINDER_WRITE_READ 与驱动交互,如果 ioctl 没有碰到中断打扰,do...while 在处理完后会返回。

详细的 BINDER_WIRTE_READ 驱动端的处理,在后面会详细分析。

5.4.2 executeCommand()

binder 线程核心处理部分,talkWithDriver() 之后对结果处理核心:

frameworks/native/libs/binder/IPCThreadState.cpp

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;

    switch ((uint32_t)cmd) {
    case BR_ERROR:
        result = mIn.readInt32();
        break;

    case BR_OK:
        break;

    case BR_ACQUIRE:
        ...
        break;

    case BR_RELEASE:
        ...
        break;

    case BR_INCREFS:
        ...
        break;

    case BR_DECREFS:
        ...
        break;

    case BR_ATTEMPT_ACQUIRE:
        ...
        break;

    case BR_TRANSACTION_SEC_CTX:
    case BR_TRANSACTION:
        ...
        break;

    case BR_DEAD_BINDER:
        ...

    case BR_CLEAR_DEATH_NOTIFICATION_DONE:
        ...

    case BR_FINISHED:
        result = TIMED_OUT;
        break;

    case BR_NOOP:
        break;

    case BR_SPAWN_LOOPER:
        mProcess->spawnPooledThread(false);
        break;

    default:
        ALOGE("*** BAD COMMAND %d received from Binder driver\n", cmd);
        result = UNKNOWN_ERROR;
        break;
    }

    if (result != NO_ERROR) {
        mLastError = result;
    }

    return result;
}

这里暂时不做分析,后续会在 native 端 C-S 中详细剖析。

至此,servicemanager 的启动流程已经梳理完毕,基本流程如下:文章来源地址https://www.toymoban.com/news/detail-503459.html

  • 根据命令行参数,选择启动设备 binder 还是设备 vndbinder
  • 通过ProcessState::initWithDriver() open、初始化设备驱动,并通过该进程的最大 thread 数量为 0;
  • 实例化 ServcieManager,并将其以特殊的 servie,注册到ServiceManager 中的mServiceMap 中;
  • 将特殊的 context obj 存放到 IPCThreadState 中,并通过 ProcessState 通知驱动context mgr;
  • 通过 BinderCallback,通知驱动servicemanger 就绪,进入 BC_ENTER_LOOPER;
  • 通过Looper 中的Epoll 将驱动设备fd 添加监听,并回调 hanleEvent();
  • 在 handleEvent() 中处理poll cmd,处理所有的信息;

到了这里,关于Android Binder通信原理(二):servicemanager启动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android Binder通信原理(五):Java 端的service 注册和获取

    源码基于: Android R 在阐述相关的知识点,先整理个框架图,后面带着框架图来分析过程: Java 端对于binder 使用大致分为: Java client Java service Java client native service Java 端service 的注册使用 ServiceManager.addService() Java 端service 的获取使用 ServiceManager.getService() 入口都是通过 Servic

    2024年02月11日
    浏览(30)
  • Binder通信原理

    注:本文大部分代码来自安卓11 ● 从IPC角度来说,Binder是Android中的一种跨进程通信方式,Binder还可以理解为一种虚拟的物理设备驱动,它的设备驱动是/dev/binder,该通信方式以前在linux中没有 ● 从Android Framework角度来说,Binder是ServiceManager连接各种Manager(ActivityManager、Windo

    2024年02月03日
    浏览(29)
  • Android Binder——Java层通信实例(十六)

            前面的文章中我们介绍了 Java 层服务的注册流程,以及代理文件的查找。这里我们看一个 Binder 通信的实例,为了方便我们就以 Android 源码中现有的功能 PMS 的 install 为例,PMS 在进行 APK 安装时,会进行 dex 的翻译,依赖守护进程 installd 完成。         在 Binder

    2024年04月23日
    浏览(38)
  • Android Binder常用案例使用分析,跨进程通信aidl

    service组件的binderService获取binder通信。 servicemanager.getService方法获取相关服务。 本质上都是IBinder通信。 客户端:使用intent,启动服务端的service,使用binderservice,在onServiceConnected回调方法中获取服务端的实际binder对象。使用aidl中的接口调用服务端的方法即可。 服务端:定义

    2024年02月07日
    浏览(35)
  • Android 进阶——Binder IPC之Binder IPC架构及原理概述(九)

    前面几篇文章,为我们学习Binder IPC通信机制提供了扎实的理论基础,接下来将正式进入Binder IPC通信架构及原理的解读。 Binder 是基于 C/S 架构的,由一系列的组件组成,包括 Client进程、Server进程、Service Manager进程、Binder 驱动。其中 Client进程、Server进程、Service Manager进程运行

    2023年04月09日
    浏览(33)
  • Android Binder机制浅谈以及使用Binder进行跨进程通信的俩种方式(AIDL以及直接利用Binder的transact方法实现)

    Binder机制学习 ·为何新增Binder来作为主要的IPC方式 Android也是基于Linux内核,Linux现有的进程通信手段有管道/消息队列/共享内存/套接字/信号量。 既然有现有的IPC方式,为什么重新设计一套Binder机制呢? 主要是出于以上三个方面的考量: 2. binder是什么? 从进程间通信的角度

    2024年02月16日
    浏览(26)
  • BpBinder与PPBinder调用过程——Android开发Binder IPC通信技术

    在Android系统中,进程间通信(IPC)是一个非常重要的话题。Android系统通过Binder IPC机制实现进程间通信,而Binder IPC通信技术则是Android系统中最为重要的进程间通信技术之一。本文将介绍Binder IPC通信技术的原理,并详细解析BpBinder与PPBinder调用过程的使用以及注意事项。 Bind

    2024年02月13日
    浏览(28)
  • 写给 Android 应用工程师的 Binder 原理剖析

    这篇文章我酝酿了很久,参考了很多学习文档,读了很多源码,却依旧不敢下笔。生怕自己理解上还有偏差,对大家造成误解,贻笑大方。又怕自己理解不够透彻,无法用清晰直白的文字准确的表达出 Binder 的设计精髓。直到今天提笔写作时还依旧战战兢兢。 Binder 之复杂远远

    2024年02月13日
    浏览(47)
  • AR 体验的“后浪,Android源码的Binder权限是如何控制

    △ 左边没有遮挡功能的“喵星人”在空间里穿越,缺乏真实感,右侧开启遮挡功能的“喵星人”则逼真地藏在了 而有了 Depth API,虚拟物体可以在现实世界找到自己的位置,和环境良好互动,让我们一起看一些优秀的使用案例。 “遮挡”掉不真实 让精彩上线 开发了 Five Nig

    2024年04月17日
    浏览(28)
  • Android源码面试宝典之JobScheduler从使用到原理分析(二)【JSS的启动】

    上文,我们以IntentService入手,先对JobScheduler进行了简单的实例编码使用。本文开始,我们开始就源码入手,开始深入学习、总结JobScheduler的内部实现原理。 我们从使用代码入手,通过阅读JobScheduler源码,来开始对于其原理,进行深入解读。

    2024年02月02日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包