Binder系列-bctest

1.打开驱动

//frameworks\native\cmds\servicemanager\bctest.c

int main(int argc, char **argv)
{
    int fd;
    struct binder_state *bs;
    uint32_t svcmgr = BINDER_SERVICE_MANAGER;
    uint32_t handle;

    bs = binder_open(128*1024);  //打开驱动
    if (!bs) { 
        fprintf(stderr, "failed to open binder driver\n");
        return -1;
    }

    //省略其他代码

    return 0;
}

2.注册服务

调用binder_call

各个参数:

  • bs:打开驱动的句柄
  • msg:包含要注册的服务的名字
  • reply:回复的内容
  • target:这里是BINDER_SERVICE_MANAGER
  • SVC_MGR_ADD_SERVICE:表示要注册服务
//frameworks\native\cmds\servicemanager\bctest.c

int svcmgr_publish(struct binder_state *bs, uint32_t target, const char *name, void *ptr)
{
    int status;
    unsigned iodata[512/4];
    struct binder_io msg, reply;

    bio_init(&msg, iodata, sizeof(iodata), 4);
    bio_put_uint32(&msg, 0);  // strict mode header
    bio_put_string16_x(&msg, SVC_MGR_NAME);
    bio_put_string16_x(&msg, name);
    bio_put_obj(&msg, ptr);

    //bs:打开驱动的句柄
    //msg:包含要注册的服务的名字
    //reply:回复的内容
    //target:这里是BINDER_SERVICE_MANAGER
    //SVC_MGR_ADD_SERVICE:表示要注册服务
    if (binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE))
        return -1;

    status = bio_get_uint32(&reply);

    binder_done(bs, &msg, &reply);

    return status;
}

3.查找服务

调用binder_call

各个参数:

  • bs:打开驱动的句柄
  • msg:包含要查找的服务的名字
  • reply:回复的内容
  • target:这里是BINDER_SERVICE_MANAGER
  • SVC_MGR_CHECK_SERVICE:表示要查找服务
//frameworks\native\cmds\servicemanager\bctest.c

uint32_t svcmgr_lookup(struct binder_state *bs, uint32_t target, const char *name)
{
    uint32_t handle;
    unsigned iodata[512/4];
    struct binder_io msg, reply;

    //构造binder_io
    bio_init(&msg, iodata, sizeof(iodata), 4);
    bio_put_uint32(&msg, 0);  // strict mode header
    bio_put_string16_x(&msg, SVC_MGR_NAME);
    bio_put_string16_x(&msg, name);

    //bs:打开驱动的句柄
    //msg:包含要查找的服务的名字
    //reply:回复的内容
    //target:这里是BINDER_SERVICE_MANAGER
    //SVC_MGR_CHECK_SERVICE:表示要查找服务
    if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
        return 0;

    handle = bio_get_ref(&reply);

    if (handle)
        binder_acquire(bs, handle);

    binder_done(bs, &msg, &reply);

    return handle;
}

4.binder_call方法

  • 将msg、target、code构造成ioctl的参数bwr
  • 调用ioctl函数
//frameworks\native\cmds\servicemanager\binder.c

//bs:
//msg:提供什么参数
//reply:返回值
//target:向谁发数据
//code:调用哪个函数
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;  //ioctl函数需要的参数是binder_write_read
    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;
    }

    //将target、code、msg 构建给bwr
    writebuf.cmd = BC_TRANSACTION;
    writebuf.txn.target.handle = target;  //target
    writebuf.txn.code = code;  //code
    writebuf.txn.flags = 0;
    writebuf.txn.data_size = msg->data - msg->data0;   //msg的数据
    writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0); //msg的数据
    writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0; //msg的数据
    writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0; //msg的数据

    bwr.write_size = sizeof(writebuf);
    bwr.write_consumed = 0;
    bwr.write_buffer = (uintptr_t) &writebuf; //将刚刚的writebuf赋值给bwr的write_buffer

    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);  //调用ioctl

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

5.client

(韦老师的视频截图) 

6.server

 (韦老师视频截图)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值