Binder - 2、servicemanager的初始化

489 阅读4分钟

一、前言

两个进程之间想要通信,就必须要知道对方的地址才行,这样的话,就必须要有一个“中间人”来做注册才行,servicemanager正是做这个事的,那又涉及到一个问题,应用进程怎么知道servicemanager的地址?看起来是一个“先有鸡还是先有蛋”的问题。我们知道,一般这种情况,我们可以将中间人设置一个大家都知道的公用地址,这样就都可以进行访问了。

二、servicemanager进程

既然是中间人,那么servicemanager就应该有一个“中立的”进程。

2.1 进程启动

servicemanager是通过.rc初始化的,在系统初始化的时候,.rc文件会被解析:

frameworks/native/cmds/servicemanager/servicemanager.rc

service servicemanager /system/bin/servicemanager
    class core animation
    user system
    group system readproc
    critical
    onrestart restart apexd
    onrestart restart audioserver
    onrestart restart gatekeeperd
    onrestart class_restart main
    onrestart class_restart hal
    onrestart class_restart early_hal
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

关于.rc的语法,我们不需要过多了解,等解析完之后,系统会将/system/bin/servicemanager文件启动为servicemanager进程,通过ps也可以看到该进程:

$ adb shell "ps -A | grep servicemanager"
system         216     1 10865356  4284 0                   0 S servicemanager

2.2 入口

servicemanager的入口是main.cpp,位置是frameworks\native\cmds\servicemanager\main.cppmain函数我们再熟悉不过了,看下代码:

int main(int argc, char** argv) {
    //获取binder驱动名
    const char* driver = argc == 2 ? argv[1] : "/dev/binder";
    //初始化Binder驱动
    sp<ProcessState> ps = ProcessState::initWithDriver(driver);
    //设置最大线程数量
    ps->setThreadPoolMaxThreadCount(0);
    ps->setCallRestriction(ProcessState::CallRestriction::FATAL_IF_NOT_ONEWAY);
    //新建ServiceManager对象
    sp<ServiceManager> manager = sp<ServiceManager>::make(std::make_unique<Access>());
    if (!manager->addService("manager", manager, false /*allowIsolated*/)
    //将ServiceManager设置到IPCThreadState
    IPCThreadState::self()->setTheContextObject(manager);
    // !!成为ContextManager
    ps->becomeContextManager();
    sp<Looper> looper = Looper::prepare(false /*allowNonCallbacks*/);
    //开启事件循环
    BinderCallback::setupTo(looper);
    ClientCallbackCallback::setupTo(looper, manager);
    while(true) {
        looper->pollAll(-1);
    }
    return EXIT_FAILURE;
}

进程启动之后,做这几件事情:

  • 1、初始化Binder驱动
  • 2、新建ServiceManager对象,并执行addService方法
  • 3、将ServiceManager设置到IPCThreadState
  • 4、成为ContextManager
  • 5、开启事件循环

2.2.1 initWithDriver

initWithDriver与我们上一次分析的init方法实际上区别不大

2.2.2 ServiceManager初始化

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

平平无奇,下一个

2.2.3 addService

Status ServiceManager::addService(const std::string& name, const sp<IBinder>& binder, bool allowIsolated, int32_t dumpPriority) {
    auto ctx = mAccess->getCallingContext();
    //异常逻辑,省略
    // Overwrite the old service if it exists
    mNameToService[name] = Service {
        .binder = binder,
        .allowIsolated = allowIsolated,
        .dumpPriority = dumpPriority
        .debugPid = ctx.debugPid,
    };
}

异常逻辑省略,主要是存到mNameToService中,方面后面获取

2.2.4 becomeContextManager

bool ProcessState::becomeContextManager()
{
    AutoMutex _l(mLock);
    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 unused = 0;
        result = ioctl(mDriverFD, BINDER_SET_CONTEXT_MGR, &unused);
    }
    return result == 0;
}

我们只关注第一个ioctl,这里调用到Binder驱动中,关键字为BINDER_SET_CONTEXT_MGR_EXT

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

看一下binder_ioctl_set_ctx_mgr


static int binder_ioctl_set_ctx_mgr(struct file *filp,
                    struct flat_binder_object *fbo)
{
    int ret = 0;
    struct binder_proc *proc = filp->private_data;
    struct binder_context *context = proc->context;
    struct binder_node *new_node;
    kuid_t curr_euid = current_euid();
    //创建Binder节点
    new_node = binder_new_node(proc, fbo);
    //修改引用计数
    new_node->local_weak_refs++;
    new_node->local_strong_refs++;
    new_node->has_strong_ref = 1;
    new_node->has_weak_ref = 1;
    //将new_node设置为binder_context_mgr_node
    context->binder_context_mgr_node = new_node;
    binder_put_node(new_node);
    return ret;
}
  • 1、创建Binder节点
  • 2、修改节点的引用计数
  • 3、设置该节点为binder_context_mgr_node,后续其他进程正是用这个来访问servicemanager

在这里我们又看到两个数据结构binder_nodebinder_context

图2.1 - binder_node的结构

struct binder_context {
    struct binder_node *binder_context_mgr_node;
    struct mutex context_mgr_node_lock;
    kuid_t binder_context_mgr_uid;
    const char *name;
};

binder_context结构相对比较简单。主要是保存binder_context_mgr_node的地址,也就是servicemanager

至此,我们将servicemanager设置给了驱动层,后面的操作就可以通过引用binder_context_mgr_node来完成了。

2.2.5 BinderCallback::setupTo

说完了becomeContextManager,我们回头看下最后一段逻辑,首先是创建一个LooperLooper我们知道是消息循环机制,然后看BinderCallback::setupTo:

static sp<BinderCallback> setupTo(const sp<Looper>& looper) {
    sp<BinderCallback> cb = sp<BinderCallback>::make();
    int binder_fd = -1;
    //获取Binder驱动的fd
    IPCThreadState::self()->setupPolling(&binder_fd);
    //添加对Binder驱动fd的监听
    int ret = looper->addFd(binder_fd,
                            Looper::POLL_CALLBACK,
                            Looper::EVENT_INPUT,
                            cb,
                            nullptr /*data*/);
    return cb;
}
  
int handleEvent(int /* fd */, int /* events */, void* /* data */) override {
    IPCThreadState::self()->handlePolledCommands();
    return 1;  // Continue receiving callbacks.
}

我们知道looper使用的是epoll机制,在收到事件的时候,就会触发这里的handleEvent,最终进入handlePolledCommands:

status_t IPCThreadState::handlePolledCommands()
{
    status_t result;
    do {
        //循环与Binder驱动通信
        result = getAndExecuteCommand();
    } while (mIn.dataPosition() < mIn.dataSize());
    processPendingDerefs();
    flushCommands();
    return result;
}

在没有事情做的时候,这个线程就会睡眠,等有事件过来,线程就被唤醒,然后开始从Binder驱动中读取数据,具体的交互逻辑我们在后面分析。

三、总结

servicemanager作为一个单独的进程存在,为其他的进程提供服务,servicemanager在启动之后,将创建出来的对象地址设置到Binder驱动层,然后进入循环,等待Binder驱动的唤醒,servicemanager初始化完毕。

图3.1 - ServiceManager初始化时序图