joshuayingwhat IT Engineer

一:Binder系统框架分析

2024-06-12

整个binder框架有2部分组成一个是ipc通信一个是rpc通讯. ipc通信机制的一般套路

源:a(client)

目的:b (server)

  1. b向servicemanager注册xx服务
  2. a向servicemanager查询xx服务,得到一个handle(handle就是指向的进程b)

数据本身:数据就是一个buffer,char[512] buffer

rpc通信:远程函数调用

  1. 调用哪一个函数:server的函数编个号
  2. 传给它什么参数:传递server的参数就放在ipc的buffer中
  3. 返回值:同样也是通过buffer传给client

client(bctest.svcmgr_lookup)

  1. open驱动
  2. 获取服务:向servicemanager查询服务得到一个指向目标进程的handle(这个handle就是目标进程server),target = 0 (表示目标进程是servicemanager)name就是client想要调用的服务 (函数)

同时SVC_MGR_GET_SERVICE也会被调用 通过handle发送数据,这个时候就会导致server从驱动中读取到数据

……

servicemanager

整个binder运行起来首先需要将servicemanager运行起来。主要做两件事一个是注册服务,另一个是查询服务。

b进程注册服务那么首先需要运行servicemanager,所以servicemanager需要做一下操作</br> 1.open驱动

2.servicemanager本身需要告诉驱动程序它就是servicemanager

3.while(true) 一个死循环,当有数据的时候才操作执行,没有数据的时候休眠。

3.1 读驱动获取数据 res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);从驱动里面读取数据

解析数据res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);

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);
        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);
                binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
            }
            ptr += sizeof(*txn);
            break;
        }

br_transaction解析数据res = func(bs, txn, &msg, &reply);其中func就是之前binder_looper传过来的svcmgr_handler。其中会根据txn→code选择不同的处理函数,是SVC_MGR_ADD_SERVICE或者SVC_MGR_GET_SERVICE函数

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;
    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(bs, 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: {
    return 0;
}

3.2 读到数据后解析数据 解析: 3.2.1.注册服务:在链表中记录名字

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;
    switch(txn->code) {
    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: {
    return 0;
}

3.2.2.获取服务:

2.1: 在链表中查询有没有这个服务

2.2:返回“server进程” 返回 handle给client(根据整数号获取对应的进程)

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;
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        if (s == NULL) {
            return -1;
        }
				//server端的进程号
        handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
        if (!handle)
            break;
        bio_put_ref(reply, handle);
        return 0;
    case SVC_MGR_LIST_SERVICES: {
    return 0;
}

server进程(bctest)

注册服务的过程:

1.open驱动

2.注册服务 2.1:向servicemanager发送调用哪个服务(函数)的名字

uint32_t svcmgr = BINDER_SERVICE_MANAGER;
svcmgr_publish(bs, svcmgr, argv[1], &token);

其中target=BINDER_SERVICE_MANAGER = 0 = servicemanager;向服务端发送消息

3.while(true) 3.1:读驱动

int binder_call(struct binder_state *bs,
                struct binder_io *msg, struct binder_io *reply,
                uint32_t target, uint32_t code)
{
    writebuf.cmd = BC_TRANSACTION;
    writebuf.txn.target.handle = target;
    writebuf.txn.code = code;
    writebuf.txn.flags = 0;
    writebuf.txn.data_size = msg->data - msg->data0;
    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;

    bwr.write_size = sizeof(writebuf);
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) &writebuf;

    hexdump(msg->data0, msg->data - msg->data0);
    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        if (res < 0) {
            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
            goto fail;
        }

        res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
        if (res == 0) return 0;
        if (res < 0) goto fail;
    }

for(;;)死循环, res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 读驱动里面的数据

3.2:解析数据,调用对应的函数

    res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0); 解析数据

binder_call分析

int binder_call(struct binder_state *bs,
                struct binder_io *msg, struct binder_io *reply,
                uint32_t target, uint32_t code)
{
    int res;
    struct binder_write_read bwr;
    struct {
        uint32_t cmd;
        struct binder_transaction_data txn;
    } __attribute__((packed)) writebuf;
    unsigned readbuf[32];

    if (msg->flags & BIO_F_OVERFLOW) {
        fprintf(stderr,"binder: txn buffer overflow\n");
        goto fail;
    }

    writebuf.cmd = BC_TRANSACTION;
    writebuf.txn.target.handle = target;
    writebuf.txn.code = code;
    writebuf.txn.flags = 0;
    writebuf.txn.data_size = msg->data - msg->data0;
    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0);
    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0;
    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0;

    bwr.write_size = sizeof(writebuf);
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) &writebuf;

    hexdump(msg->data0, msg->data - msg->data0);
    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);

        if (res < 0) {
            fprintf(stderr,"binder: ioctl failed (%s)\n", strerror(errno));
            goto fail;
        }

        res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
        if (res == 0) return 0;
        if (res < 0) goto fail;
    }

fail:
    memset(reply, 0, sizeof(*reply));
    reply->flags |= BIO_F_IOERROR;
    return -1;
}

远程调用:

首先向谁发数据 —→ target=目标进程

调用哪个函数 ——>code = 目标进程函数的id

提供什么参数 ——> msg

返回值是什么 —→reply

int binder_call(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply, uint32_t target, uint32_t code)

1.构造函数:放在buffer中,用binder_io来描述;

2.调用ioctl发送数据;

参考连接: https://cs.android.com/android/platform/superproject/+/android-cts-6.0_r28:frameworks/native/cmds/servicemanager/service_manager.c


Similar Posts

Content