binder守护进程servicemanager简介

简介

  • servicemanager 进程
    1. 主要任务是什么?
    2. 实现机制;

。启动流程

servicemanager 是一个可执行程序,由于起优先级很高,所以在init进程起来后,很快会被fork出来,下面是servicemanager进程的启动配置:

service servicemanager /system/bin/servicemanager
    class core  ->声明为core类型进程,将最先被init进程fork出来执行.
    user system
    group system readproc  -> 什么服务所在进程组和相关权限
    critical -> 声明为关键进程,若死掉次数超过4次,将会触发linux kernel重启
    onrestart restart healthd
    onrestart restart zygote
    onrestart restart audioserver
    onrestart restart media
    onrestart restart surfaceflinger
    onrestart restart inputflinger
    onrestart restart drm
    onrestart restart cameraserver ->上面这些重要的进程的启动需要依赖servicemanager进程
    writepid /dev/cpuset/system-background/tasks

所以可以看出,servicemanager进程在init进程起来后会以最高优先级启动,因为很多重要的进程,比如zygote、surfaceflinger、media等都需要依赖它的存在,若servicemanager进程启动异常,显然Android系统是启动不了的。 这里简单介绍了servicemanager的启动优先级以及一些进程依赖关系,下面重点看下它启动后具体干了什么事情。

源码路径:

frameworks$ find ./ -name service_manager.c
./native/cmds/servicemanager/service_manager.c

首先看main函数实现:

int main()
{
    struct binder_state *bs;

/* Open /dev/binder设备,使用mmap映射一块128kb的内存与之关联,
   内核中对应的操作是为 struct binder_proc *proc; 结构实例申请内存,初始化赋值当前进程等操作,申请size为128kb的虚拟内存,添加到虚拟内存管理数据结构中.
*/
    bs = binder_open(128*1024);
    if (!bs) {
        ALOGE("failed to open binder driver\n");
        return -1;
    }

/* 下发BINDER_SET_CONTEXT_MGR的command,声明为binder上下文管理,内核中对应结构是:struct binder_node *binder_context_mgr_node; */
    if (binder_become_context_manager(bs)) {
        ALOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

... /* 略过selinux相关检查 */

/* 进入for(;;)轮询,不断从binder驱动中获取解析cmd数据,若cmd
是 BR_TRANSACTION 类型,则回调 svcmgr_handler 函数,该函数主要实现的功能
主要是:ADD,GET,CHECK,LIST 服务等操作,新ADD的服务最终会通过do_add_service函数接口添加到svcinfo *svclist 数据结构实例中使用链表管理起来,以便实现GET,CHECK,LIST service等操作,系统服务只有注册到servicemanager的这个svclist中才能够实现被统一管理.
*/
    binder_loop(bs, svcmgr_handler);

    return 0;
}

需要注意的一点是,所有的这些ADD/GET service都是封装后的数据,属于binder的一套协议,svcinfo 结构如下:

struct svcinfo
{
    struct svcinfo *next;
    uint32_t handle;
    struct binder_death death;
    int allow_isolated;
    size_t len;
    uint16_t name[0]; -> 保存service的name,而实际通过binder 驱动传输数据过程是传输一个uint16_t类型数据.
};

初始化主流程图:servicemanager初始化小结:

。打开/dev/binder设备,kernel对应操作就是初始化binder_proc数据结构实例;

。使用mmap系统调用建立一块128k的虚拟内存映射到binder驱动;

。声明binder上下文管理守护进程,kernel对应的就是初始化binder_context_mgr_node结构;

。进入binder消息轮询,等待client消息到来;

现在有个问题,上面初始化完成后,是如何工作的呢?也就是消息轮询是怎么做的呢?下面以add service这个消息来简单梳理下工作流程.

先看binder_loop的实现:

void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr;
    uint32_t readbuf[32];
...
    /* ioctl 知会binder驱动开始进入looper */
    readbuf[0] = BC_ENTER_LOOPER;
    binder_write(bs, readbuf, sizeof(uint32_t));

    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        
        /* 从驱动中取出bwr message */
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

...
        /* 解析 bwr message */
        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
...
    }
}

重点是binder_parse函数的实现:

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) {
...
        case BR_TRANSACTION: {
            struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
            if ((end - ptr) < sizeof(*txn)) {
                ALOGE("parse: txn too small!\n");
                return -1;
            }
            binder_dump_txn(txn);
            if (func) {
                unsigned rdata[256/4];
                struct binder_io msg;
                struct binder_io reply;
                int res;
                
                /* 转换取出binder传输数据到binder io */
                bio_init(&reply, rdata, sizeof(rdata), 4);
                bio_init_from_txn(&msg, txn);
                
                /* 当解析到cmd=BR_TRANSACTION的时候回调svcmgr_handler 函数 */
                res = func(bs, txn, &msg, &reply);
                /* ONE_WAY 属于异步类型,所以不需要等待返回结果*/
                if (txn->flags & TF_ONE_WAY) {
                    binder_free_buffer(bs, txn->data.ptr.buffer);
                } else {
                /* 否则默认同步调用,发送BC_REPLY的CMD到驱动,告知等待返回结果 */
                    binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
                }
            }
            ptr += sizeof(*txn);
            break;
        }
...
    }

    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;
    
    /* 转换获取service的name */
    s = bio_get_string16(msg, &len);
...
    switch(txn->code) {
    /* getService() || checkService() */
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        /* 查询svclist链表中已有的service */
        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:
        /* addService() */
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
        handle = bio_get_ref(msg);
        allow_isolated = bio_get_uint32(msg) ? 1 : 0;
        
        /* add service 的真正实现,将新的service最终添加
           到svclist这个单 链表中管理起来
        */
        if (do_add_service(bs, s, len, handle, txn->sender_euid,
            allow_isolated, txn->sender_pid))
            return -1;
        break;
...
    /* add service成功,把reply存入bio结构实例中 */
    bio_put_uint32(reply, 0);
    return 0;
}

add service 流程图: image


从图上可以看出在servicemanager里面,add service要做的事情其实也不复杂:

。解析出cmd == BR_TRANSACTION,回调svcmgr_handler函数;

。执行do_add_service动作,将新的svc添加到svclist链表中管理;

。回复消息给binder驱动;

所以servicemanager主要干的事情是:

  • 实现所有的系统服务注册管理,所有的系统服务信息保存到全局链表svclist中的维护;

  • 作为守护进程,轮询binder驱动(/dev/binder)来实现两个进程间的binder协议数据交互,为binder机制提供服务;




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值