美文网首页
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