servicemanager的启动简介

Android2023年8月18日 am8:08发布11个月前更新 3XCN.COM站长
1 0 0
广告也精彩
目录

前言

Android源码分析《mediaserver的启动》时涉及到mediaserver服务的添加和获取(之前没有细说),而管理这些服务的就是servicemanager这个类,也就是今天介绍的主角。

涉及文件

frameworks\native\cmds\servicemanager\service_manager.c
frameworks\native\cmds\servicemanager\servicemanager.rc
frameworks\native\cmds\servicemanager\binder.c
frameworks\native\cmds\servicemanager\Android.bp

正文

这里只是简单的走一下流程,知道servicemanager是一个服务管理者,提供服务的注册和查询功能。

servicemanager的启动

根据之前源码分析,知道大部分服务都是在init中解析rc文件启动的。

servicemanager的启动rc文件是servicemanager.rc。

# servicemanager.rc
# 源码中()
frameworks\native\cmds\servicemanager\servicemanager.rc
# Android设备中
/system/etc/init

跟mediaserver一样,也是在init中解析/system/etc/init时启动的。

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

service_manager.c代码会走两次,因为有两个服务公用一套代码。

#@站长
frameworks\native\cmds\servicemanager\Android.bp

会发现

# Android.bp中部分
//略
cc_binary {
    name: "servicemanager",
    defaults: ["servicemanager_flags"],
    srcs: [
        "service_manager.c",
        "binder.c",
    ],
    shared_libs: ["libcutils", "libselinux"],
    init_rc: ["servicemanager.rc"],
}

cc_binary {
    name: "vndservicemanager",
    defaults: ["servicemanager_flags"],
    vendor: true,
    srcs: [
        "service_manager.c",
        "binder.c",
    ],
    cflags: [
        "-DVENDORSERVICEMANAGER=1",
    ],
    shared_libs: ["libcutils", "libselinux"],
    init_rc: ["vndservicemanager.rc"],
}

从上面会发现servicemanager和vndservicemanager公用service_manager.c一套代码,只是参数不一样。

vndservicemanager的.rc文件是vndservicemanager.rc启动的。

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

PS:后续只关注servicemanager哈

service_manager.c

程序的入口都是main()。

主要做了如下几个工作:

  1. 打开binder驱动

  2. 成为上下文管理者

  3. 进入binder循环,处理客户端发送的请求

int main(int argc, char** argv){
    struct binder_state *bs;
    union selinux_callback cb;
    char *driver;
   //vndservicemanager的启动带参数的(argc > 1),servicemanager的启动不带参数(argc == 1)
    if (argc > 1) {
        driver = argv[1]; //是/dev/vndbinder
    } else {
        driver = "/dev/binder";
    }
    //打开binder驱动,申请128k字节大小的内存空间
    bs = binder_open(driver, 128*1024);
    if (!bs) {
#ifdef VENDORSERVICEMANAGER
        while (true) {
            sleep(UINT_MAX);
        }
#else
        ALOGE("failed to open binder driver %s\n", driver);
#endif
        return -1;
    }
    //成为上下文管理者
    if (binder_become_context_manager(bs)) {
        return -1;
    }
    cb.func_audit = audit_callback;
    selinux_set_callback(SELINUX_CB_AUDIT, cb);
    cb.func_log = selinux_log_callback;
    selinux_set_callback(SELINUX_CB_LOG, cb);
    //获取sehandle,这里分vndservicemanager和servicemanager
#ifdef VENDORSERVICEMANAGER
    sehandle = selinux_android_vendor_service_context_handle();
#else
    sehandle = selinux_android_service_context_handle();
#endif
    selinux_status_open(true);
    //无法获取sehandle
    if (sehandle == NULL) {
        abort();
    }
    //无法获取service_manager上下文就退出
    if (getcon(&service_manager_context) != 0) {
        abort();
    }
    //进入无限循环,处理client端发来的请求
    binder_loop(bs, svcmgr_handler);
    return 0;
}
打开binder驱动
//125啦站长
//打开binder驱动,申请128k字节大小的内存空间
//driver="/dev/binder"
bs = binder_open(driver, 128*1024);
binder_open()

这里主要工作

  1. 给bs分配内存

  2. 通过open打开设备驱动,返回文件描述符并赋值给bs->fd

  3. 内核空间和用户空间的binder版本比较

  4. mmap内存映射

涉及kernel层代码的方法,推荐看末尾参考文章,我这略过

struct binder_state *binder_open(const char* driver, size_t mapsize){
    struct binder_state *bs;
    struct binder_version vers;
    //申请内存
    bs = malloc(sizeof(*bs));
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }
    //打开Binder设备驱动,返回文件描述符并赋值给bs->fd
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
    if (bs->fd < 0) {
        //打开失败就进入fail_open
        goto fail_open;
    }
    //获取binder版本信息并对比
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
        //内核空间与用户空间的binder不是同一版本
        goto fail_open;
    }
    //传入的值=128k
    bs->mapsize = mapsize;
    //mmap内存映射
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    if (bs->mapped == MAP_FAILED) {
        //binder设备内存无法映射
        goto fail_map;
    }
    return bs;
fail_map:
    close(bs->fd);
fail_open:
    free(bs);
    return NULL;
}
成为上下文管理者
//成为上下文管理者
if (binder_become_context_manager(bs)) {
    return -1;
}
binder_become_context_manager()

成为上下文的管理者,整个系统中只有一个这样的管理者。

int binder_become_context_manager(struct binder_state *bs){
    //通过ioctl,传递BINDER_SET_CONTEXT_MGR指令
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
进入binder循环
//进入无限循环,处理client端发来的请求
binder_loop(bs, svcmgr_handler);

这里传入的是svcmgr_handler指针函数。

先看binder_loop()

binder_loop()

这里主要如下工作

  1. 通过binder_write通知binder驱动要进入循环

  2. 通过ioctl读取binder中的数据

  3. 通过binder_parse解析数据

void binder_loop(struct binder_state *bs, binder_handler func){
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];
    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;
    readbuf[0] = BC_ENTER_LOOPER;
    //将BC_ENTER_LOOPER命令发送给binder驱动,让Service Manager进入循环
    binder_write(bs, readbuf, sizeof(uint32_t));
    //进入循环
    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        //不断地binder读写过程
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        if (res < 0) {
            break;
        }
        //解析binder信息,这里传入了func哈
        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
        if (res == 0) {
            break;
        }
        if (res < 0) {
            break;
        }
    }
}
binder_write()

对data数据进行封装成binder_write_read,然后通过ioctl()发送给binder

int binder_write(struct binder_state *bs, void *data, size_t len){
    struct binder_write_read bwr;
    int res;
    bwr.write_size = len;
    bwr.write_consumed = 0;
    //传入的是BC_ENTER_LOOPER
    bwr.write_buffer = (uintptr_t) data; 
    bwr.read_size = 0;
    bwr.read_consumed = 0;
    bwr.read_buffer = 0;
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    return res;
}
binder_parse()

这里传入了svcmgr_handler,也就是func

这里主要功能

  1. 获取cmd码,根据cmd进行处理对应功能

  2. 处理BR_TRANSACTION事务,主要通过func处理(也就是svcmgr_handler)

这里部分不太懂,后续学习。请看参考文吧。多谢、

int binder_parse(struct binder_state *bs, struct binder_io *bio,uintptr_t ptr, size_t size, binder_handler func){
    int r = 1;
    uintptr_t end = ptr + (uintptr_t) size;
    while (ptr < end) {
        //获取cmd码
        uint32_t cmd = *(uint32_t *) ptr;
        ptr += sizeof(uint32_t);
        //处理解析到的cmd码
        switch(cmd) {
        case BR_NOOP://无操作,退出循环
            break;
        case BR_TRANSACTION_COMPLETE:
            break;
        case BR_INCREFS:
        case BR_ACQUIRE:
        case BR_RELEASE:
        case BR_DECREFS:
            ptr += sizeof(struct binder_ptr_cookie);
            break;
        case BR_TRANSACTION: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if ((end - ptr) < sizeof(*txn)) {
                return -1;
            }
            binder_dump_txn(txn);
            //binder_handler函数不为null
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
                struct binder_io reply;
                int res;
                bio_init(&reply, rdata, sizeof(rdata), 4);
                //从txn解析出binder_io信息
                bio_init_from_txn(&msg, txn);
                //通过binder_handler函数进行处理
                res = func(bs, txn, &msg, &reply);
                if (txn->flags & TF_ONE_WAY) {
                    //不需要回复,释放buffer
                    binder_free_buffer(bs, txn->data.ptr.buffer);
                } else {
                    //需要回复,添加恢复信息并释放buffer
                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
                }
            }
            ptr += sizeof(*txn);
            break;
        }
        case BR_REPLY: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if ((end - ptr) < sizeof(*txn)) {
                return -1;
            }
            binder_dump_txn(txn);
            if (bio) {
                //从txn解析出binder_io信息
                bio_init_from_txn(bio, txn);
                bio = 0;
            } else {
                /* todo FREE BUFFER */
            }
            ptr += sizeof(*txn);
            r = 0;
            break;
        }
        case BR_DEAD_BINDER: {
            // binder死亡消息
            struct binder_death *death = (struct binder_death *)(uintptr_t) *(binder_uintptr_t *)ptr;
            ptr += sizeof(binder_uintptr_t);
            death->func(bs, death->ptr);
            break;
        }
        case BR_FAILED_REPLY:
            r = -1;
            break;
        case BR_DEAD_REPLY:
            r = -1;
            break;
        default:
            ALOGE("parse: OOPS %d\n", cmd);
            return -1;
        }
    }
    return r;
}
svcmgr_handler()

servicemanager是个服务管理者,用于保存启动过的服务,并提供查询服务等功能。

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply){
    //略
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE://获取服务和检查服务
         //服务名
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
         //根据名称查找相应handle
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        //调用bio_put_ref(reply, handle),将handle封装到reply.
        bio_put_ref(reply, handle);
        return 0;
    case SVC_MGR_ADD_SERVICE://添加服务
        //服务名
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        dumpsys_priority = bio_get_uint32(msg);
        //添加服务到svclist
        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,txn->sender_pid))
            return -1;
        break;
    case SVC_MGR_LIST_SERVICES: {
        uint32_t n = bio_get_uint32(msg);
        uint32_t req_dumpsys_priority = bio_get_uint32(msg);
        if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
            return -1;
        }
        si = svclist;
        //遍历
        while (si) {
            if (si->dumpsys_priority & req_dumpsys_priority) {
                if (n == 0) break;
                n--;
            }
            si = si->next;
        }
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
    default:
        return -1;
    }
    bio_put_uint32(reply, 0);
    return 0;
}
do_find_service()
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) {
        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;
    }
    //返回该服务所对应的handle
    return si->handle;
}
do_add_service()
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;
    if (!handle || (len == 0) || (len > 127))
        return -1;
    //权限检查
    if (!svc_can_register(s, len, spid, uid)) {
        return -1;
    }
     //服务检索 判断是否有存在的服务
    si = find_svc(s, len);
    if (si) {
        if (si->handle) {
            //服务已注册时,释放之前的服务
            svcinfo_death(bs, si);
        }
        //更新handle
        si->handle = handle;
    } else {
        //如果之前没有,就创建并保存
        si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
        if (!si) {
            //内存不足,无法分配足够内存
            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保存所有已注册的服务
        svclist = si;
    }
    //以BC_ACQUIRE命令,handle为目标的信息,通过ioctl发送给binder驱动
    binder_acquire(bs, handle);
    //以BC_REQUEST_DEATH_NOTIFICATION命令的信息,通过ioctl发送给binder驱动
    //主要用于清理内存等收尾工作。
    binder_link_to_death(bs, handle, &si->death);
    return 0;
}

参考文章

  1. Binder系列3—启动ServiceManager

  2. ServiceManager与binder驱动的交互

 历史上的今天

版权声明 1、 本站名称: 91易搜
2、 本站网址: 91es.com3xcn.com
3、 本站文章: 部分来源于网络,仅供站长学习和参考,若侵权请留言
广告也精彩

相关文章

广告也精彩

暂无评论

评论审核已启用。您的评论可能需要一段时间后才能被显示。

暂无评论...

网站升级中

公告

近期网站升级中,可能存在一些bug。欢迎反馈 https://www.91es.com/we.html

本站域名

本站域名 : 91es.com3xcn.com。本站邮箱 : 站长邮箱 i@oorr.cn,通知邮箱we@oorr.cn ,如有更新,请看公告 。