美文网首页
binder(一)使用流程

binder(一)使用流程

作者: 曾大稳丶 | 来源:发表于2021-05-31 14:15 被阅读0次

servicemanager

1. 打开驱动
struct binder_state *bs;
bs = binder_open(128*1024);

2. 注册为管家
binder_become_context_manager(bs)

3. 开启循环接受和解析数据
sehandle = selinux_android_service_context_handle();
binder_loop(bs, svcmgr_handler);

server

1. 打开驱动
binder_open

2. 注册到servicemanager
binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE)

3. 开启循环接受和解析数据

int res;
struct binder_write_read bwr;
struct {
    uint32_t cmd;
    struct binder_transaction_data txn;
} __attribute__((packed)) writebuf;
unsigned readbuf[32];

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;


for (;;) {
    res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
    res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);
}

client

1. 打开驱动
binder_open

2. 从servicemanager获取到server handler
binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE)

3. 传递数据
binder_call(g_bs, &msg, &reply, g_hello_handle, HELLO_SVR_CMD_SAYHELLO_TO)

4. 拿到返回数据
ptr = bio_get_ref(&reply);

数据传输

client--->service

client

  1. client 构造参数 binder_write_read
struct binder_write_read {
    binder_size_t       write_size; /* bytes to write */
    binder_size_t       write_consumed; /* bytes consumed by driver */
    binder_uintptr_t    write_buffer;
    binder_size_t       read_size;  /* bytes to read */
    binder_size_t       read_consumed;  /* bytes consumed by driver */
    binder_uintptr_t    read_buffer;
};

1.1. binder_write_read内部结构writebuf标识binder驱动执行的cmd(BC_TRANSACTION/BC_ENTER_LOOPER)和相关具体数据binder_transaction_data

struct {
        //  BC_TRANSACTION/BC_ENTER_LOOPER
        uint32_t cmd;
        struct binder_transaction_data txn;
} __attribute__((packed)) writebuf;

1.2 writebuf内结构体binder_transaction_data标识目标服务,目标函数以及参数等,code代表具体执行的函数标识,比如add_service,check_service,buffer代表参数

struct binder_transaction_data {
    /* The first two are only used for bcTRANSACTION and brTRANSACTION,
     * identifying the target and contents of the transaction.
     */
    union {
        /* target descriptor of command transaction */
        __u32   handle;
        /* target descriptor of return transaction */
        binder_uintptr_t ptr;
    } target;
    binder_uintptr_t    cookie; /* target object cookie */
    __u32       code;       /* transaction command */

    /* General information about the transaction. */
    __u32           flags;
    pid_t       sender_pid;
    uid_t       sender_euid;
    binder_size_t   data_size;  /* number of bytes of data */
    binder_size_t   offsets_size;   /* number of bytes of offsets */

    /* If this transaction is inline, the data immediately
     * follows here; otherwise, it ends with a pointer to
     * the data buffer.
     */
    union {
        struct {
            /* transaction data */
            binder_uintptr_t    buffer;
            /* offsets from buffer to flat_binder_object structs */
            binder_uintptr_t    offsets;
        } ptr;
        __u8    buf[8];
    } data;
};

  1. 通过ioctl发送数据
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
  1. 解析返回数据
 res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0);

完整的client发送代码

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];
   
    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;
   
    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;
    }

}

service端

  1. 注册到servicemanager
  2. 开启循环接受数据
  3. 通过ioctl接受到数据解析成binder_write_read
  4. 通过binder_write_readcmdreadbuf执行对应的函数, 会把readbuf转成binder_transaction_data,具体代码查看

service代码

//开启循环
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;
    binder_write(bs, readbuf, sizeof(uint32_t));
    for (;;) {
        bwr.read_size = sizeof(readbuf);
        bwr.read_consumed = 0;
        bwr.read_buffer = (uintptr_t) readbuf;
        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);

        switch(cmd) {
        //...
        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);
                res = func(bs, txn, &msg, &reply);
                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;
            //...
            break;
        }
        
        //...
       }
    return r;
}


示例demo :github

相关文章

网友评论

      本文标题:binder(一)使用流程

      本文链接:https://www.haomeiwen.com/subject/gbhbsltx.html