Android 系统服务管家servicemanager启动过程详解

Android考虑到移动设备耗电以及跨进程通信效率等因素,基于OpenBinder专门为进程通信开发了一套框架:binder。例如,客户端程序需要获取WindowManager,TelephonyManager等系统服务时,就需要通过binder这个中介来负责数据与指令的传输。那么,Android提供了如此多的系统服务(可达上百个,可通过 adb shell service list查看),又是谁在负责管理这些服务了?Android为此专门提供了一个系统管家servicemanagerservicemanager主要负责添加服务,获取服务,查找服务以及当某个服务意外终止时,对该服务的资源进行回收。ServiceManager跨越了两个框架层:Java层、C++层。这篇文章先看一看native(C)层的具体实现原理。

源码路径:

  • C++: /android/frameworks/native/cmds/servicemanager/
  • Java: /android/frameworks/base/core/java/android/os/

servicemanager的启动

Android在init进程启动以后,通过脚本init.rc,启动ServiceManager:

    service servicemanager /system/bin/servicemanager
    class core
    user system
    group system
    critical
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart keystore

service_manager.c中找到对应的main()函数,这是servicemanager启动的入口:

    int main()
    {
        struct binder_state *bs;
        // 打开binder
        bs = binder_open(128*1024);
        if (!bs) {
            ALOGE("failed to open binder driver\n");
            return -1;
        }
        // 成为系统服务的管家
        if (binder_become_context_manager(bs)) {
            ALOGE("cannot become context manager (%s)\n", strerror(errno));
            return -1;
        }
        ....
        // 进入binder循环
        binder_loop(bs, svcmgr_handler);

        return 0;
    }

main函数里主要做了三件事:一是打开binder文件节点,并分配IPC所需的内存;二让ServiceManager成为系统服务的管家(context manager);三开启相应的工作线程,并循环处理IPC请求。

binder_open

函数binder_open()主要作用:(1)打开binder设备文件,获取到对应的文件描述符,(2)从Binder驱动获取binder版本号,(3)接着创建一个binder内存区域,用于跨进程数据的交换(这里大小为128K)。

    struct binder_state *binder_open(size_t mapsize)
    {
        struct binder_state *bs;
        struct binder_version vers;
        // 为binder_state分配内存空间
        bs = malloc(sizeof(*bs));
        if (!bs) {
            errno = ENOMEM;
            return NULL;
        }
        // 打开Binder驱动对应的文件节点,最终调用驱动函数binder_open
        bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
        // 获取当前Binder版本号
        if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
            (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
            fprintf(stderr,
                    "binder: kernel driver version (%d) differs from user space version (%d)\n",
                    vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
            goto fail_open;
        }
        //分配一块只读内存区域,用于IPC交换数据,最终调用binder驱动接口binder_mmap
        bs->mapsize = mapsize;
        bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
        if (bs->mapped == MAP_FAILED) {
            fprintf(stderr,"binder: cannot map device (%s)\n",
                    strerror(errno));
            goto fail_map;
        }

        return bs;

        fail_map:
            close(bs->fd);
        fail_open:
            free(bs);
            return NULL;
    }

binder相关的ioctl指令定义在 /android/kernel/drivers/staging/android/uapi/binder.h

    #define BINDER_WRITE_READ       _IOWR('b', 1, struct binder_write_read)
    #define BINDER_SET_IDLE_TIMEOUT     _IOW('b', 3, __s64)
    #define BINDER_SET_MAX_THREADS      _IOW('b', 5, __u32)
    #define BINDER_SET_IDLE_PRIORITY    _IOW('b', 6, __s32)
    #define BINDER_SET_CONTEXT_MGR      _IOW('b', 7, __s32)
    #define BINDER_THREAD_EXIT      _IOW('b', 8, __s32)
    #define BINDER_VERSION          _IOWR('b', 9, struct binder_version)

binder驱动提供了诸如ioctl,mmap,open,flush等操作,在驱动初始化时会将其注册到系统中

    static const struct file_operations binder_fops = {
    .owner = THIS_MODULE,
    .poll = binder_poll,
    .unlocked_ioctl = binder_ioctl,
    .compat_ioctl = binder_ioctl,
    .mmap = binder_mmap,
    .open = binder_open,
    .flush = binder_flush,
    .release = binder_release,
    };

    static struct miscdevice binder_miscdev = {
        .minor = MISC_DYNAMIC_MINOR,
        .name = "binder",
        .fops = &binder_fops
    };

binder_become_context_manager

    int binder_become_context_manager(struct binder_state *bs)
    {
        // 系统调用,告知binder驱动,ServiceManager将成为系统服务管家,对应的handle为0
        return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
    }

系统调用ioctl最终会调用binder驱动对应的操作函数。查看binder驱动的代码,在/android/kernel/drivers/staging/android/binder.c中有一个函数binder_ioctl,这就是用于处理kernel系统调用ioctl对应的指令,找到请求BINDER_SET_CONTEXT_MGR对应的代码,在设置系统服务管家完成后,返回对应的结果。

    static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
    {
        int ret;
        struct binder_proc *proc = filp->private_data;
        struct binder_thread *thread;
        unsigned int size = _IOC_SIZE(cmd);
        void __user *ubuf = (void __user *)arg;

        ret = wait_event_interruptible(binder_user_error_wait, binder_stop_on_user_error < 2);
        // 加锁
        binder_lock(__func__);
        thread = binder_get_thread(proc);

        switch (cmd) {
            ....
            // 设置服务管家
            case BINDER_SET_CONTEXT_MGR:
                ret = binder_ioctl_set_ctx_mgr(filp);
                if (ret)
                    goto err;
                break;
            ....
            // 查询Binder版本
            case BINDER_VERSION: {
                struct binder_version __user *ver = ubuf;

                if (put_user_preempt_disabled(BINDER_CURRENT_PROTOCOL_VERSION, &ver->protocol_version)) {
                    ret = -EINVAL;
                    goto err;
                }
                break;
            }
            default:
                ret = -EINVAL;
                goto err;
        }
        ret = 0;
        ....
    }

binder_loop

    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;
        // 让ServiceManager线程进入循环
        binder_write(bs, readbuf, sizeof(uint32_t));

        for (;;) {
            bwr.read_size = sizeof(readbuf);
            bwr.read_consumed = 0;
            bwr.read_buffer = (uintptr_t) readbuf;
            // 读取 driver中的数据
            res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
            // 解析读取到的数据,并通过svcmgr_handler进行处理
            res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
            ....
        }
    }

读取到binder驱动缓冲区域里的数据后,解析之:

    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) {
            uint32_t cmd = *(uint32_t *) ptr;
            ptr += sizeof(uint32_t);

            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 (func) {
                    unsigned rdata[256/4];
                    struct binder_io msg;
                    struct binder_io reply;
                    int res;

                    bio_init(&reply, rdata, sizeof(rdata), 4);
                    bio_init_from_txn(&msg, txn);
                    // 处理客户端请求,func就是函数svcmgr_handler
                    res = func(bs, txn, &msg, &reply);
                    if (txn->flags & TF_ONE_WAY) {
                        binder_free_buffer(bs, txn->data.ptr.buffer);
                    } else {
                        // 发送回复给客户端
                        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)) {
                    ALOGE("parse: reply too small!\n");
                    return -1;
                }
                binder_dump_txn(txn);
                if (bio) {
                    bio_init_from_txn(bio, txn);
                    bio = 0;
                } else {
                    /* todo FREE BUFFER */
                }
                ptr += sizeof(*txn);
                r = 0;
                break;
            }
            case BR_DEAD_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;
            ....
            default:
                ALOGE("parse: OOPS %d\n", cmd);
                return -1;
            }
        }

        return r;
    }

svcmgr_handler处理客户端的请求,如添加服务,查找服务以及获取服务等。

    int svcmgr_handler(struct binder_state *bs,
                       struct binder_transaction_data *txn,
                       struct binder_io *msg,
                       struct binder_io *reply)
    {
        struct svcinfo *si;
        uint16_t *s;
        size_t len;
        uint32_t handle;
        uint32_t strict_policy;
        int allow_isolated;

        if (txn->target.ptr != BINDER_SERVICE_MANAGER)
            return -1;

        if (txn->code == PING_TRANSACTION)
            return 0;   
        ....
        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 = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
            if (!handle)
                break;
            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;
            if (do_add_service(bs, s, len, handle, txn->sender_euid,
                allow_isolated, txn->sender_pid))
                return -1;
            break;

        case SVC_MGR_LIST_SERVICES: {
            uint32_t n = bio_get_uint32(msg);

            if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
                ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
                        txn->sender_euid);
                return -1;
            }
            si = svclist;
            while ((n-- > 0) && si)
                si = si->next;
            if (si) {
                bio_put_string16(reply, si->name);
                return 0;
            }
            return -1;
        }
        default:
            ALOGE("unknown code %d\n", txn->code);
            return -1;
        }

        bio_put_uint32(reply, 0);
        return 0;
    }

这里总结下ServiceManager进程启动的过程,其流程简图如下:

  • binder_open(): 打开驱动设备节点,并为进程分配一个128K大小的内存区域用于IPC数据交换;
  • binder_become_context_manager(): 使servicemanager称为系统服务的管家;
  • binder_loop(): 进入线程执行状态,等待客户端程序的请求

Start Service Manager

参考文献

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值