Android学习笔记(一)ServiceManager

ServiceManager

  1. 简介

ServiceManager功能相当于所有服务(Service)的一个管理器,是一个标准的Binder Service

  1. ServiceManager的启动

ServiceManager是通过init.rc\system\core\rootdir\init.rc)启动的。

init.rc中相关代码:

service servicemanager /system/bin/servicemanager   àservice(指令,可执行程序) <name><pathname>

    class core àclass<name>为服务指定一个名,统一class的所有服务必须同启同停

    user system àuser<username>在启动服务前将用户切换至<username>,默认root

    group systemàgroup<groupname>在启动服务前将用户组切换至<groupname>

    critical à表明对设备至关重要的一个服务,四分钟退出超过四次,设备将重启进入恢复模式

    onrestart restart healthdàonrestart标识重启时执行某些命令

    onrestart restart zygote

    onrestart restart media

    onrestart restart surfaceflinger

onrestart restart drm

ServiceManager是用C/C++编写的,源码路径在:\frameworks\native\cmds\servicemanager\ service_manager.c

相关的make\frameworks\native\cmds\servicemanager\Android.mk)文件如下:

LOCAL_PATH:= $(call my-dir)

#include $(CLEAR_VARS)

#LOCAL_SRC_FILES := bctest.c binder.c

#LOCAL_MODULE := bctest

#include $(BUILD_EXECUTABLE)

include $(CLEAR_VARS)

LOCAL_SHARED_LIBRARIES := liblog

LOCAL_SRC_FILES := service_manager.c binder.cà相关的源文件

LOCAL_MODULE := servicemanager à生成可执行文件

include $(BUILD_EXECUTABLE)à指向一个编译脚本,收集自从上次调用 include $(CLEAR_VARS)  后的所有LOCAL_XXX信息。并决定如何将你列出的Source编译成一个可执行Native程序。

ServiceManager启动的工作:

int main(int argc, char **argv)

{

    struct binder_state *bs;

    void *svcmgr = BINDER_SERVICE_MANAGER;

    bs = binder_open(128*1024);

    if (binder_become_context_manager(bs)) {à设置为Binder管家,整个系统仅此一处

        ALOGE("cannot become context manager (%s)\n", strerror(errno));

        return -1;

    }

    svcmgr_handle = svcmgr;

    binder_loop(bs, svcmgr_handler);

    return 0;

}

首先给变量svcmgr赋初值,宏定义如下:

/* \frameworks\native\cmds\servicemanager\binder.h */

/* the one magic object */

#define BINDER_SERVICE_MANAGER ((void*) 0)

接下来调用binder_open打开Binder设备,相关源码如下:

/* \frameworks\native\cmds\servicemanager\binder.c */

struct binder_state *binder_open(unsigned mapsize)

{

    struct binder_state *bs;à结构体记录ServiceManagerBinder相关信息,如fdmap大小等 

    bs = malloc(sizeof(*bs));

    if (!bs) {

        errno = ENOMEM;

        return 0;

    }

 

    bs->fd = open("/dev/binder", O_RDWR);à打开Binder驱动节点

    if (bs->fd < 0) {

        fprintf(stderr,"binder: cannot open device (%s)\n",

                strerror(errno));

        goto fail_open;

}

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;

    }

        /* TODO: check version */

    return bs;

fail_map:

    close(bs->fd);

fail_open:

    free(bs);

    return 0;

}

 

mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存,对于应用程序而言,它通过mmap返回值得到一个内存(当然这是虚拟地址),这个地址通过虚拟内存转换(分段、分页)后最终指向物理内存的某个位置。

此处通过mmap的调用实现了以下目的:

  • Binder驱动决定被映射到进程空间中的内存起始地址;

  • 映射区块大小为128K

  • 映射区只读

  • 映射区的改变是私有的,不需要保存文件

  • 从文件的起始地址开始映射

接下来的步骤是将ServiceManager注册成为Binder机制“管家”:

/* \frameworks\native\cmds\servicemanager\binder.c */

int binder_become_context_manager(struct binder_state *bs)

{

    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);

}

通过ioctl指令函数发送BINDER_SET_CONTEXT_MGR指令,完成注册。

准备工作就绪,接下来,ServiceManager开始等待客户端的请求,binder_loop(bs, svcmgr_handler);

/* \frameworks\native\cmds\servicemanager\binder.c */

void binder_loop(struct binder_state *bs, binder_handler func)

{

    int res;

    struct binder_write_read bwr;à执行BINDER_WRITE_READ指令所需的数据结构

    unsigned readbuf[32];à一次读取容量

 

    bwr.write_size = 0;

    bwr.write_consumed = 0;

    bwr.write_buffer = 0; 

    readbuf[0] = BC_ENTER_LOOPER;à BC_REGISTER_LOOPER通知 驱动线程池中一个线程已经创建了;BC_ENTER_LOOPER通知驱动该线程已经进入主循环,可以接收数据;BC_EXIT_LOOPER通知驱动该 线程退出主循环,不再接收数据。(待看)

    binder_write(bs, readbuf, sizeof(unsigned));àBC_ENTER_LOOPER写入Binder驱动

 

    for (;;) {

        bwr.read_size = sizeof(readbuf);

        bwr.read_consumed = 0;

        bwr.read_buffer = (unsigned) readbuf;

 

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);à读取消息

 

        if (res < 0) {

            ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));

            break;

        }

 

        res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); à处理消息

        if (res == 0) {

            ALOGE("binder_loop: unexpected reply?!\n");

            break;

        }

        if (res < 0) {

            ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));

            break;

        }

    }

}

随后ServiceManager进入循环中,和典型的基于事件驱动的程序框架类似,进入循环后做的主要工作如下:

  • 从消息队列中读取消息

  • 如果消息是退出指令,则结束循环;如果消息为空,则继续读取或等待后再读取;如果消息可以运行,则执行指令。

  • 如此循环直到退出

指令的解析和执行是通过binder_parse函数完成的。

/* \frameworks\native\cmds\servicemanager\binder.c */

int binder_parse(struct binder_state *bs, struct binder_io *bio,

                 uint32_t *ptr, uint32_t size, binder_handler func)

{

    int r = 1;

    uint32_t *end = ptr + (size / 4);à一个uint32_t占用4个字节

    while (ptr < end) {

        uint32_t cmd = *ptr++;à一个cmd占用一个uint32_t,获取后跳过

#if TRACE

        fprintf(stderr,"%s:\n", cmd_name(cmd));

#endif

        switch(cmd) {

        case BR_NOOP:à 操作完成

            break;

        case BR_TRANSACTION_COMPLETE:à 发送方通过BC_TRANSACTIONBC_REPLY发送完一个数据包后,都能收到该消息做为成功发送的反馈。这和BR_REPLY不一样, 是驱动告知发送方已经发送成功,而不是接收方返回请求数据。所以不管同步还是异步交互接收方都能获得本消息。

            break;

        case BR_INCREFS:à BR_INCREFS/BR_ACQUIRE/BR_RELEASE/BR_DECREFS这一组消息用于管理强/弱指针的引用计数。只有提供Binder实体的进程才能收到这组消息

        case BR_ACQUIRE:

        case BR_RELEASE:

        case BR_DECREFS:

#if TRACE

            fprintf(stderr,"  %08x %08x\n", ptr[0], ptr[1]);

#endif

            ptr += 2;

            break;

        case BR_TRANSACTION: {à这两条消息分别对应发送方的BC_TRANSACTIONBC_REPLY,表示当前接收的数据是请求或是回复。

            struct binder_txn *txn = (void *) ptr;

            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) {

                ALOGE("parse: txn too small!\n");

                return -1;

            }

            binder_dump_txn(txn);àdump追踪

            if (func) {à这个函数为svcmgr_handler()

                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);

                res = func(bs, txn, &msg, &reply);à具体的消息处理函数

                binder_send_reply(bs, &reply, txn->data, res);à回应消息处理结果

            }

            ptr += sizeof(*txn) / sizeof(uint32_t);à处理完成,跳过这一段数据

            break;

        }

        case BR_REPLY: {

            struct binder_txn *txn = (void*) ptr;

            if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_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) / sizeof(uint32_t)); à处理完成,跳过这一段数据

            r = 0;

            break;

        }

        case BR_DEAD_BINDER: {

            struct binder_death *death = (void*) *ptr++;

            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;

}

BR_TRANSACTION消息:

BR_TRANSACTION消息的处理主要是通过funcsvcmgr_handler函数)完成的,主要完成以下功能:

  • 注册:当一个Binder Server创建后,它们要将自己的[名称,Binder句柄]对应关系告知ServiceManager进行备案。

  • 查询:应用程序可以向ServiceManager发起查询请求,以获知某个Binder Service所对应的句柄。

  • 其他信息查询:如ServiceManager版本号、当前状态等。

/* \frameworks\native\cmds\servicemanager\service_manager.c */

int svcmgr_handler(struct binder_state *bs,

                   struct binder_txn *txn,

                   struct binder_io *msg,

                   struct binder_io *reply)

{

    struct svcinfo *si;

    uint16_t *s;

    unsigned len;

    void *ptr;

    uint32_t strict_policy;

    int allow_isolated;

 

 

    if (txn->target != svcmgr_handle)

        return -1;

 

    strict_policy = bio_get_uint32(msg);

    s = bio_get_string16(msg, &len);

    if ((len != (sizeof(svcmgr_id) / 2)) ||

        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {

        fprintf(stderr,"invalid id %s\n", str8(s));

        return -1;

}àbio_XX系列函数为取出各种类型的数据提供了便利

 

    switch(txn->code) {

    case SVC_MGR_GET_SERVICE:à以下两个指令是一样的,都是根据Server查找handle

    case SVC_MGR_CHECK_SERVICE:

        s = bio_get_string16(msg, &len);

        ptr = do_find_service(bs, s, len, txn->sender_euid);à这个函数执行查找操作,ServiceManager中维护一个全局的svc list变量,用于保存所有server的注册信息。

        if (!ptr)

            break;

        bio_put_ref(reply, ptr);

        return 0;

 

    case SVC_MGR_ADD_SERVICE:à用于注册一个Binder Server

        s = bio_get_string16(msg, &len);

        ptr = bio_get_ref(msg);

        allow_isolated = bio_get_uint32(msg) ? 1 : 0;

        if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated)à添加操作

            return -1;

        break;

 

    case SVC_MGR_LIST_SERVICES: {à获取列表中的对应server

        unsigned n = bio_get_uint32(msg);

 

        si = svclist;à所有server信息保存在这个list

        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;

}

 

转载于:https://my.oschina.net/honeyandroid/blog/504202

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值