XJBX-5-Android启动ServiceManager

427 阅读3分钟

ServiceManager简介

ServiceManager也是Android系统中的核心进程,主要负责Binder架构中的binder管理,前面介绍过在Init.rc中启动。在Binder进程间通信,是必不可少的中转角色。

image.png 源码路径frameworks/native/cmds/servicemanager/service_manager.c。

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
    writepid /dev/cpuset/system-background/tasks
    shutdown critical

在启动ServiceManager时,还需要做一些准备。在main函数中,首先通过binder_open打开/dev/binder设备初始化,Linux中一切皆文件,binder驱动也有对应的文件描述符。还有一件重要的事情是使用mmap方式创建一块内存,128*1024,主要用于数据传输。这个内存相对于Java使用的内存当然很小,但是在内核中,保存一下句柄数据,通信指令数据,其实是足够的。binder_become_context_manager函数是将本进程设置成Binder管理进程,随后开启binder_loop,循环读取消息。

int main(int argc, char** argv)
{
    struct binder_state *bs;
    union selinux_callback cb;
    char *driver;

    if (argc > 1) {
        driver = argv[1];
    } else {
        driver = "/dev/binder";
    }
    bs = binder_open(driver, 128*1024);
    if (!bs) {
#ifdef VENDORSERVICEMANAGER
        ALOGW("failed to open binder driver %s\n", driver);
        while (true) {
            sleep(UINT_MAX);
        }
#else
        ALOGE("failed to open binder driver %s\n", driver);
#endif
        return -1;
    }

    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }
    binder_loop(bs, svcmgr_handler);

    return 0;
}

ServiceManager主要功能

注册Binder服务
Binder的注册功能,一句话描述就是将进程对应的Binder驱动节点保存在一个链表中,进行监听,通信和死亡通知。通过当前进程的PID,检查是否有权限注册,接着查看Binder服务是否已经注册过。最终创建对应的svcinfo的结构,保存服务的名称等信息,最后存放在svclist中。

int do_add_service(struct binder_state *bs, const uint16_t *s, size_t len, uint32_t handle,
                   uid_t uid, int allow_isolated, uint32_t dumpsys_priority, pid_t spid) {
    struct svcinfo *si;

    //ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
    //        allow_isolated ? "allow_isolated" : "!allow_isolated", uid);

    if (!handle || (len == 0) || (len > 127))
        return -1;

    if (!svc_can_register(s, len, spid, uid)) {
        ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
             str8(s, len), handle, uid);
        return -1;
    }

    si = find_svc(s, len);
    if (si) {
        if (si->handle) {
            ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
                 str8(s, len), handle, uid);
            svcinfo_death(bs, si);
        }
        si->handle = handle;
    } else {
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
                 str8(s, len), handle, uid);
            return -1;
        }
        si->handle = handle;
        si->len = len;
        memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
        si->name[len] = '\0';
        si->death.func = (void*) svcinfo_death;
        si->death.ptr = si;
        si->allow_isolated = allow_isolated;
        si->dumpsys_priority = dumpsys_priority;
        si->next = svclist;
        svclist = si;
    }

    binder_acquire(bs, handle);
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

查询Binder服务
查询BInder服务,这个很好理解,将进程对应的binder文件节点从svclist中遍历寻找出,获取对应的binder服务。

uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
    struct svcinfo *si = find_svc(s, len);

    if (!si || !si->handle) {
        return 0;
    }

    if (!si->allow_isolated) {
        // If this service doesn't allow access from isolated processes,
        // then check the uid to see if it is isolated.
        uid_t appid = uid % AID_USER;
        if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
            return 0;
        }
    }

    if (!svc_can_find(s, len, spid, uid)) {
        return 0;
    }

    return si->handle;
}

源码好无聊,有兴趣自己去看吧,说了那么多,面试的时候你知道该怎么吹了吧......