前面对Binder的用途和通信过程涉及的代码进行了概述,这章主要用C来实现一个client和server,说再多不如代码体现的直接,下面的附上代码,代码都做了详细的注解,理解起来比较容易。
第一个程序是向Service_manager注册一个服务,编写一个test_server.c程序
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <linux/types.h> #include <stdbool.h> #include <string.h> #include <private/android_filesystem_config.h> #include "binder.h" #include "test_server.h" 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); /* 使用binder_call去访问ServiceManager 的 addService 函数 */ 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; } void sayhello(void) { static int cnt = 0; /* 简单的做个打印 */ fprintf(stderr, "say hello : %d\n", cnt++); } int sayhello_to(char *name) { static int cnt = 0; /* 简单的做个打印 */ fprintf(stderr, "say hello to %s: %d\n", name, cnt++); return 888;//验证是否client能收到这个值 } /* 注册完service便开始等待client传来数据用以下这个函数来进行处理 */ int hello_service_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) { /* 根据txn->code知道要调用哪一个函数 * 如果需要参数,可以从msg取出 * 如果要返回结果,可以把结果放入reply */ /* 提供两个函数: * sayhello * sayhello_to */ uint16_t *s; char name[512]; size_t len; uint32_t handle; uint32_t strict_policy; int i; // Equivalent to Parcel::enforceInterface(), reading the RPC // header with the strict mode policy mask and the interface name. // Note that we ignore the strict_policy and don't propagate it // further (since we do no outbound RPCs anyway). strict_policy = bio_get_uint32(msg); /* 根据txn->code知道要调用service的哪个函数 */ switch(txn->code) { case HELLO_SVR_CMD_SAYHELLO: sayhello(); return 0; case HELLO_SVR_CMD_SAYHELLO_TO: /* 从msg里取出字符串 */ //string是16位的,需要转换为8位的 s = bio_get_string16(msg, &len); if(s == NULL){ return -1; } for(i=0; i<len; i++){ name[i] = s[i]; } name[i] = '\0'; /* 处理传递进来的参数 */ i= sayhello_to(name); /* 把结果放入reply,使用bind_loop返回去 */ bio_put_uint32(reply, i); break; default: fprintf(stderr, "unknown code %d\n", txn->code); return -1; } bio_put_uint32(reply, 0); return 0; } int main(int argc, char **argv) { int fd; struct binder_state *bs; uint32_t svcmgr = BINDER_SERVICE_MANAGER; uint32_t handle; int ret; /* 打开binder驱动程序 */ bs = binder_open(128*1024); if (!bs) { fprintf(stderr, "failed to open binder driver\n"); return -1; } /* 添加一个服务 */ //svcmgr: 向ServiceManager发送数据 //"hello": 服务的名称 //最后一个参数是指针 ret = svcmgr_publish(bs, svcmgr, "hello", (void *)123); if (ret) { fprintf(stderr, "failed to publish hello service\n"); return -1; } /* 再添加一个服务 */ //新添加的服务后面这个指针参数(124)不能一样, 否则会失败 ret = svcmgr_publish(bs, svcmgr, "goodbye", (void *)124); if (ret) { fprintf(stderr, "failed to publish googbye service\n"); } /* 一个循环,一旦检测到有数据进来就调用service_handler */ binder_loop(bs, hello_service_handler); return 0; }第二个程序是test_client,我想实现显示hello的服务,但不清楚谁能提供,所以需要去service_manager里面找下谁能帮我把hello显示出来,client代码如下:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <linux/types.h> #include <stdbool.h> #include <string.h> #include <private/android_filesystem_config.h> #include "binder.h" #include "test_server.h" 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参数是想要获取service的名字 */ 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; /* 得到服务的handler(句柄) */ handle = bio_get_ref(&reply); /* 申请服务 */ if (handle) binder_acquire(bs, handle); binder_done(bs, &msg, &reply); return handle; } struct binder_state *g_bs; uint32_t g_handle; /* 如果获取服务返回成功,则调用binder_call进行通信 */ void sayhello(void) { /* 构造binder_io */ unsigned iodata[512/4]; struct binder_io msg, reply; bio_init(&msg, iodata, sizeof(iodata), 4); bio_put_uint32(&msg, 0); // strict mode header /* 调用binder_call */ if (binder_call(g_bs, &msg, &reply, g_handle, HELLO_SVR_CMD_SAYHELLO)) return ; /* 表明已经处理完了 */ binder_done(g_bs, &msg, &reply); } int sayhello_to(char *name) { /* 构造binder_io */ unsigned int ret; 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, name); /* 调用binder_call */ if (binder_call(g_bs, &msg, &reply, g_handle, HELLO_SVR_CMD_SAYHELLO_TO)) return 0; /* 从reply中解析出返回值 */ ret = bio_get_uint32(&reply); /* 表明已经处理完了 */ binder_done(g_bs, &msg, &reply); return ret; } /* 如何使用这个client * ./test_client hello * ./test_client hello <name> */ int main(int argc, char **argv) { int fd; struct binder_state *bs; uint32_t svcmgr = BINDER_SERVICE_MANAGER; uint32_t handle; int ret; /* 参数判断 */ if(argc < 2){ fprintf(stderr, "Usage:\n"); fprintf(stderr, "%s hello\n", argv[0]); fprintf(stderr, "%s hello <name>\n", argv[0]); return -1; } /* 打开binder驱动 */ bs = binder_open(128*1024); if (!bs) { fprintf(stderr, "failed to open binder driver\n"); return -1; } g_bs = bs; /* 获取hello服务 */ handle = svcmgr_lookup(bs, svcmgr, "hello"); if(!handle){ fprintf(stderr, "failed to get hello driver\n"); return -1; } g_handle = handle; /* 发送数据到hello服务里面,获取返回值 */ if(argc == 2){ sayhello(); }else if(argc == 3){ ret = sayhello_to(argv[2]); /* 打印返回值 */ fprintf(stderr, "get ret of sayhello_to = %d\n", ret); } /* client 使用完就释放服务 */ binder_release(bs, handle); return 0; }