目录:
-
Android : 跟我学Binder --- (1) 什么是Binder IPC?为何要使用Binder机制?
-
Android : 跟我学Binder --- (2) AIDL分析及手动实现
-
Android : 跟我学Binder --- (3) C程序示例
-
Android : 跟我学Binder --- (4) 驱动情景分析
-
Android : 跟我学Binder --- (5) server的多线程实现(未写)
-
Android : 跟我学Binder --- (6) c++实现_(未写)
-
Android : 跟我学Binder --- (7) JAVA实现_(未写)
一、数据结构
首先基于之前的c程序代码再添加一个goodbye服务,引入以下几个概念:
binder_ref
binder_node
binder_proc
binder_thread
binder_buffer
1.test_server.c中实现goodbye服务处理函数:
int goodbye_service_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) { /* 根据txn->code知道要调用哪一个函数 * 如果需要参数, 可以从msg取出 * 如果要返回结果, 可以把结果放入reply */ /* saygoodbye * saygoodbye_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); switch(txn->code) { case GOODBYE_SVR_CMD_SAYGOODBYE: saygoodbye(); bio_put_uint32(reply, 0); /* no exception */ return 0; case GOODBYE_SVR_CMD_SAYGOODBYE_TO: /* 从msg里取出字符串(16位转8位) */ s = bio_get_string16(msg, &len); //"IGoodbyeService" s = bio_get_string16(msg, &len); // name if (s == NULL) { return -1; } for (i = 0; i < len; i++) name[i] = s[i]; name[i] = ‘\0‘; /* 处理 */ i = saygoodbye_to(name); /* 把结果放入reply */ bio_put_uint32(reply, 0); /* no exception */ bio_put_uint32(reply, i); break; default: fprintf(stderr, "unknown code %d\n", txn->code); return -1; } return 0; }
2.main函数中注册服务:
/* add service */ ret = svcmgr_publish(bs, svcmgr, "hello", hello_service_handler); if (ret) { fprintf(stderr, "failed to publish hello service\n"); return -1; } ret = svcmgr_publish(bs, svcmgr, "goodbye", goodbye_service_handler); if (ret) { fprintf(stderr, "failed to publish goodbye service\n"); } ...... binder_loop(bs, test_server_handler); //通过函数test_server_handler处理消息
其中 test_server_handler 会根据binder_transaction_data中的descriptor信息调用对应服务的处理函数:
int test_server_handler(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply) { int (*handler)(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply); handler = (int (*)(struct binder_state *bs, struct binder_transaction_data *txn, struct binder_io *msg, struct binder_io *reply))txn->target.ptr; return handler(bs, txn, msg, reply); // 根据txn->target.ptr转换成对应的处理函数 }
3.test_client.c中获取服务并使用:
/* get service */ handle = svcmgr_lookup(bs, svcmgr, "goodbye"); if (!handle) { fprintf(stderr, "failed to get goodbye service\n"); return -1; } g_goodbye_handle = handle; fprintf(stderr, "Handle for goodbye service = %d\n", g_goodbye_handle);
/* use service */ void saygoodbye(void) { 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, "IGoodbyeService"); /* 放入参数 */ /* 调用binder_call */ if (binder_call(g_bs, &msg, &reply, g_goodbye_handle, GOODBYE_SVR_CMD_SAYGOODBYE)) return ; /* 从reply中解析出返回值 */ binder_done(g_bs, &msg, &reply); }
通过分别对hello和goodbye服务的注册/获取,注册和获取打印的handle值并不对应相同,这就涉及到IPC的概念:①源(自己)、②目的(handle表示)、③数据;
例如调用binder_call:
if (binder_call(g_bs, &msg, &reply, g_goodbye_handle, GOODBYE_SVR_CMD_SAYGOODBYE)) return ;
其原型为:
/* *@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)
binder驱动会根据handle找到目的进程,驱动内部通过 binder_ref 管理对应的引用:
struct binder_ref { int debug_id; struct rb_node rb_node_desc; struct rb_node rb_node_node; struct hlist_node node_entry; struct binder_proc *proc; struct binder_node *node; uint32_t desc; int strong; int weak; struct binder_ref_death *death; };
binder_ref添加逻辑,如图:
二、打印数据交互过程
从前面编写的示例程序可知,与binder驱动交互主要是通过ioctl操作:
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
传入的数据为 struct binder_write_read bwr,该结构体中的 write_buffer 指向数据本身,对应结构体如下:
struct {
uint32_t cmd; //头4个字节表示数据类型
struct binder_transaction_data txn;
} __attribute__((packed)) writebuf;
三、服务注册/获取/使用过程
四、transaction_stack机制