Android Binder(C语言版本)

Posted we1less

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Binder(C语言版本)相关的知识,希望对你有一定的参考价值。

android中存在用c语言写的Binder应用,接下来以这个文件开始分析

当进行Binder通信过程中


main    frameworks/native/cmds/servicemanager/service_manager.c

1.打开Binder驱动

int main(int argc, char** argv)
{
    ...

    if (argc > 1) {
        driver = argv[1];
    } else {
        driver = "/dev/binder";
    }

    bs = binder_open(driver, 128*1024);
    if (!bs) {
#ifdef VENDORSERVICEMANAGER
        ALOGW("failed to open binder driver %s\\n", driver);
        while (true) {
            sleep(UINT_MAX);
        }
#else
        ALOGE("failed to open binder driver %s\\n", driver);
#endif
        return -1;
    }

main    frameworks/native/cmds/servicemanager/service_manager.c

2.告诉驱动,此进程是service_manager    

if (binder_become_context_manager(bs)) {
    ALOGE("cannot become context manager (%s)\\n", strerror(errno));
    return -1;
}

3.循环  main    frameworks/native/cmds/servicemanager/service_manager.c

binder_loop(bs, svcmgr_handler);

binder_loop    frameworks/native/cmds/servicemanager/binder.c

3.1读驱动获取数据

void binder_loop(struct binder_state *bs, binder_handler func)
{
    ...
    for (;;) {
        ...
        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        ...
}

binder_parse    frameworks/native/cmds/servicemanager/binder.c

3.2解析数据

void binder_loop(struct binder_state *bs, binder_handler func)
{
    ...
    for (;;) {
        ...
        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;
        }
    }
}

svcmgr_handler    frameworks/native/cmds/servicemanager/service_manager.c 

对于解析数据后处理是由3里面的svcmgr_handler回调处理  (根据code调用不同函数)

int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    ...
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        ...
    case SVC_MGR_ADD_SERVICE:
        ...
    case SVC_MGR_LIST_SERVICES: {
        ...
    }
    default:
        ALOGE("unknown code %d\\n", txn->code);
        return -1;
    }

    bio_put_uint32(reply, 0);
    return 0;
}

3.3调用    a.注册服务(在链表中记录服务名称)          

SVC_MGR_CHECK_SERVICE  查询服务
SVC_MGR_ADD_SERVICE    注册服务

                 b.返回“server”进程的handle


service

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

1.打开Binder驱动     

bs = binder_open("/dev/binder", 128*1024);

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

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

    argc--;
    argv++;
    while (argc > 0) {
        if (!strcmp(argv[0],"alt")) {
            ...
        } else if (!strcmp(argv[0],"lookup")) {
            ...;
        } else if (!strcmp(argv[0],"publish")) {
            ...
            svcmgr_publish(bs, svcmgr, argv[1], &token);
            argc--;
            argv++;
        } else {
            fprintf(stderr,"unknown command %s\\n", argv[0]);
            return -1;
        }
        argc--;
        argv++;
    }
    return 0;
}

2.注册服务(向service_manager发送服务名称)

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

  binder_call(bs, &msg, &reply, target, SVC_MGR_ADD_SERVICE)

  target  要把数据发送给哪个进程

  这个例子中  target  为  uint32_t svcmgr = BINDER_SERVICE_MANAGER;

                                                         #define BINDER_SERVICE_MANAGER 0U

  target  发  0 代表把数据发给  service_manager

  SVC_MGR_ADD_SERVICE  表示要调用service_manager

                                                             (3.3)SVC_MGR_ADD_SERVICE  注册服务函数

  &msg   含有服务的名字

  &reply  service_manager回复的数据

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

    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.循环    3.1读驱动获取数据

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


client

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

1.打开Binder驱动  (与上相同)

bs = binder_open("/dev/binder", 128*1024);

2.获取服务   

handle = svcmgr_lookup(bs, svcmgr, "alt_svc_mgr");

binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE)

  target  要把数据发送给哪个进程

  0  向service_manager获取服务

  SVC_MGR_CHECK_SERVICE表示要调用service_manager中的

                                                             (3.3)SVC_MGR_CHECK_SERVICE 获取服务函数

  &msg   含有服务的名字

  &reply  service_manager回复的数据,表示提供服务的进程

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;

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

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

 2.1向service_manager查询服务

                     2.2获取handle

3.向这个handle发送数据


binder_call  frameworks/native/cmds/servicemanager/binder.c

  target  向谁发数据

  code  调用哪个函数

  *msg  提供哪个参数

  *reply  返回值

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

binder_call  如何用

1.构造参数  struct binder_io

2.调用  ioctl  发数据  

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

  struct binder_write_read bwr;

  其中存在参数转换成驱动&bwr的过程  (struct binder_io -->  struct binder_write_read)

3.  ioctl  收数据  收到binder_write_read

  还需要将  (struct binder_write_read -->  struct binder_io)

以上是关于Android Binder(C语言版本)的主要内容,如果未能解决你的问题,请参考以下文章

Android Binder ServiceManager启动源码分析

Android——Binder

Android Binder(C++版本)

Android C++语言 通过Binder通信调用activity: [android.app.IActivityManager] 服务发广播

Android binder介绍

Android Binder 跟踪