Android源码阅读---Service Manager进程

Android源码阅读—Service Manager进程


ServiceManager 是 android中IPC机制的关键组件,它是一个bin可执行程序,由init进程开启并作为一个系统服务一直运行,主要为各个bind客户端提供服务查询、为binder服务端提供注册等功能,如果没有该该服务, android的binder机制将无法正常工作。

1. 编译命令

include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := liblog libcutils libselinux
LOCAL_SRC_FILES := service_manager.c binder.c
LOCAL_CFLAGS += $(svc_c_flags)
LOCAL_MODULE := servicemanager
LOCAL_INIT_RC := servicemanager.rc
include $(BUILD_EXECUTABLE)

从这个编译命令来看,这个bin程序涉及到的源文件并不多,主要有service_manager.c和binder.c,然后它的配置文件单独拿出来,存放在编译文件同级目录下

service servicemanager /system/bin/servicemanager
    class core
    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
    writepid /dev/cpuset/system-background/tasks
    onrestart restart filelock

从配置文件可以看出,该servicemanager 属于core组,一旦该服务重启,其他系统服务如healthd、zygote、audioserver等也会restart
然后在init.rc中,在boot触发阶段有一个class_start core的 command, 它对应的函数static int do_class_start(const std::vector<std::string>& args)将会start服务块链表中class为core的service,因为servicemanager 也属于core组,所以在boot触发阶段,init进程也会开启一个子进程,然后让子进程开始运行servicemanager。

on boot
    # basic network init
    ifup lo
    hostname localhost
    domainname localdomain

    # Memory management. Basic kernel parameters, and allow the high
    # level system server to be able to adjust the kernel OOM driver
    # parameters to match how it is managing things.
    write /proc/sys/vm/overcommit_memory 1
/*省略*/
    # Define default initial receive window size in segments.
    setprop net.tcp.default_init_rwnd 60
    class_start core

2. main函数流程

分析一个bin进程,首先看看它的 main函数,在该main函数中主要做了:

  1. 使用函数binder_open打开binder设备
  2. 将自己设置为binder
  3. binder_loop循环
int main()
{
    struct binder_state *bs;
    bs = binder_open(128*1024);/*128k*/
    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;
    }
    selinux_enabled = is_selinux_enabled();
    sehandle = selinux_android_service_context_handle();
    selinux_status_open(true);
    if (selinux_enabled > 0) {
        if (sehandle == NULL) {
            ALOGE("SELinux: Failed to acquire sehandle. Aborting.\n");
            abort();
        }
        if (getcon(&service_manager_context) != 0) {
            ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\n");
            abort();
        }
    }
    union selinux_callback cb;
    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);
    binder_loop(bs, svcmgr_handler);
    return 0;
}

3. 打开binder设备

binder_open主要是做一个内存映射的工作,核心在函数mmap中,

struct binder_state
{
    int fd;
    void *mapped;
    size_t mapsize;
};
struct binder_state *binder_open(size_t mapsize)
{
    struct binder_state *bs;
    struct binder_version vers;
    bs = malloc(sizeof(*bs));/*为结构体binder_state 分配空间,该结构体中记录了关于binder的信息*/
    if (!bs) {
        errno = ENOMEM;
        return NULL;
    }
    bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);/*打开驱动节点*/
    if (bs->fd < 0) {
        fprintf(stderr,"binder: cannot open device (%s)\n",
                strerror(errno));
        goto fail_open;
    }
    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;
    }
    bs->mapsize = mapsize;/* 设定的为128k*/
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);/*到此,结构体binder_state 填充完成*/
    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;
}

4. 将自己设置为binder

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);/*使用命令BINDER_SET_CONTEXT_MGR将自己设置为 binder 管家*/
}

5. loop循环

循环的做下面2步操作

  • 对binder驱动执行读信息
  • 将拿到的信息进行处理
void binder_loop(struct binder_state *bs, binder_handler func)
{
    int res;
    struct binder_write_read bwr; /*binder读写需要的格式*/
/*
struct binder_write_read {
  binder_size_t write_size;
 binder_size_t write_consumed;
// WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS 
  binder_uintptr_t write_buffer;
  binder_size_t read_size;
 binder_size_t read_consumed;
 binder_uintptr_t read_buffer;
// WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS 
};
*/
    uint32_t readbuf[32]; /* 数据读取的缓冲空间*/

    bwr.write_size = 0;
    bwr.write_consumed = 0;
    bwr.write_buffer = 0;

    readbuf[0] = BC_ENTER_LOOPER;
    binder_write(bs, readbuf, sizeof(uint32_t));/*会把readbuf数据写到binder驱动中中*/
/*开始循环*/
    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;/*会把数据读到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, (uintptr_t) 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;
        }
    }/*for 循环结束*/
}

5.1 从binder中读数据

从binder中支持 ioctl(bs->fd, BINDER_WRITE_READ, &bwr)读取操作并把数据写入到readbuf中

5.2 解析数据

将第一步读取到的数据进行解析,具体实现在函数binder_parse中执行
首先,将数据中的第一个uint32_t 作为一个cmd命令
然后,根据cmd命令来判断执行各种的逻辑

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;/*将第一个uint32_t   取出来 存到临时变量cmd 中,后续根据这个cmd 指令觉定走哪个switch语句*/
        ptr += sizeof(uint32_t);/*然后指针向下移动一个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 ((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;

                bio_init(&reply, rdata, sizeof(rdata), 4);
                bio_init_from_txn(&msg, txn);
                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;
        case BR_DEAD_REPLY:
            r = -1;
            break;
        default:
            ALOGE("parse: OOPS %d\n", cmd);
            return -1;
        }
    }
    return r;
}

然后主要看看BR_TRANSACTION、BR_REPLY、BR_DEAD_BINDER这3个命令做了什么操作

5.2.1 BR_TRANSACTION

        case BR_TRANSACTION: {
/*如果smd是BR_TRANSACTION 命令,后面直接当成是binder_transaction_data 类型数据*/
/*
struct binder_transaction_data {
// WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS 
  union { __u32 handle; binder_uintptr_t ptr;} target;
//WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS
  binder_uintptr_t cookie;
  __u32 code;
  __u32 flags;
  pid_t sender_pid;
  uid_t sender_euid;
  binder_size_t data_size;
  binder_size_t offsets_size;
  union { struct {binder_uintptr_t buffer; binder_uintptr_t offsets; } ptr;
    __u8 buf[8];
  } data;
};
*/
            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;
                bio_init(&reply, rdata, sizeof(rdata), 4); /*初始化bio对象*/
                bio_init_from_txn(&msg, txn);
                res = func(bs, txn, &msg, &reply);/*主要使用函数svcmgr_handler来处理txn中的数据,然后结果存在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);/* 再偏移binder_transaction_data 个位置,因为这部分数据已经处理了*/
            break;
        }

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)/*如果从binder驱动读到的信息不是发给sm的就退出*/
        return -1;

    if (txn->code == PING_TRANSACTION)
        return 0;

    // Equivalent to Parcel::enforceInterface(), reading the RPC header with the strict mode policy mask and the interface name.
    // Note that we ignore the strict_policy and don't propagate it further (since we do no outbound RPCs anyway).
    strict_policy = bio_get_uint32(msg);
    s = bio_get_string16(msg, &len);
    if (s == NULL) {
        return -1;
    }

    if ((len != (sizeof(svcmgr_id) / 2)) ||
        memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
        fprintf(stderr,"invalid id %s\n", str8(s, len));
        return -1;
    }
    if (sehandle && selinux_status_updated() > 0) {
        struct selabel_handle *tmp_sehandle = selinux_android_service_context_handle();
        if (tmp_sehandle) {
            selabel_close(sehandle);
            sehandle = tmp_sehandle;
        }
    }
/*然后又根据binder_transaction_data 面的code 执行不同的case
1. SVC_MGR_CHECK_SERVICE和SVC_MGR_GET_SERVICE都是通过字符串s中的名字来得到对应server的handle
2. SVC_MGR_ADD_SERVICE用来注册一个server
3. SVC_MGR_LIST_SERVICES用来获取整个server列表
*/
    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);/*具体的查找函数,根据s来查找对应handle */
        if (!handle)
            break;
        bio_put_ref(reply, handle);/*将handle通过reply返回给上层调用函数*/
        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;
}

所以在binder_parse函数中,如果读到的信息中cmd命令是BR_TRANSACTION,表示有他进程在向sm进行服务的查询或者注册等,而sm主要的功能就是对服务的管理,看来sm主要逻辑就是走这个switch分支了。所以到此,整个service manager二进制程序的主要逻辑就了解完了。

5.2.2 BR_REPLY

和service manager程序相关性不大,

5.23 BR_DEAD_BINDER

和service manager程序相关性不大,

在这里插入图片描述

参考 《深入理解android内核设计思想》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值