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

Posted Jason_Wang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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(): 进入线程执行状态,等待客户端程序的请求

参考文献

以上是关于Android 系统服务管家servicemanager启动过程详解的主要内容,如果未能解决你的问题,请参考以下文章

Android如何注册服务到ServiceManager?

手机控车OBD-移动管家手机控车方案基于Android手机智能控制汽车系统的研究与实现;

Android系统启动-综述—1

Android Binder 框架层详解

“创管家”,服务于中小家装小企业的SAAS系统!

智能电视都有哪些操作系统?沙发管家带你涨知识!