整个binder框架有2部分组成一个是ipc通信一个是rpc通讯. ipc通信机制的一般套路
源:a(client)
目的:b (server)
- b向servicemanager注册xx服务
- a向servicemanager查询xx服务,得到一个handle(handle就是指向的进程b)
数据本身:数据就是一个buffer,char[512] buffer
rpc通信:远程函数调用
- 调用哪一个函数:server的函数编个号
- 传给它什么参数:传递server的参数就放在ipc的buffer中
- 返回值:同样也是通过buffer传给client
client(bctest.svcmgr_lookup)
- open驱动
- 获取服务:向servicemanager查询服务得到一个指向目标进程的handle(这个handle就是目标进程server),target = 0 (表示目标进程是servicemanager)name就是client想要调用的服务 (函数)
同时SVC_MGR_GET_SERVICE也会被调用 通过handle发送数据,这个时候就会导致server从驱动中读取到数据
……
servicemanager
整个binder运行起来首先需要将servicemanager运行起来。主要做两件事一个是注册服务,另一个是查询服务。
b进程注册服务那么首先需要运行servicemanager,所以servicemanager需要做一下操作</br> 1.open驱动
2.servicemanager本身需要告诉驱动程序它就是servicemanager
3.while(true) 一个死循环,当有数据的时候才操作执行,没有数据的时候休眠。
3.1 读驱动获取数据 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);
case BR_TRANSACTION: {
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
if ((end - ptr) < sizeof(*txn)) {
ALOGE("parse: txn too small!\n");
return -1;
}
binder_dump_txn(txn);
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;
}
br_transaction解析数据res = func(bs, txn, &msg, &reply);其中func就是之前binder_looper传过来的svcmgr_handler。其中会根据txn→code选择不同的处理函数,是SVC_MGR_ADD_SERVICE或者SVC_MGR_GET_SERVICE函数
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
return 0;
}
3.2 读到数据后解析数据 解析: 3.2.1.注册服务:在链表中记录名字
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
switch(txn->code) {
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
return 0;
}
3.2.2.获取服务:
2.1: 在链表中查询有没有这个服务
2.2:返回“server进程” 返回 handle给client(根据整数号获取对应的进程)
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
//server端的进程号
handle = do_find_service(bs, s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_LIST_SERVICES: {
return 0;
}
server进程(bctest)
注册服务的过程:
1.open驱动
2.注册服务 2.1:向servicemanager发送调用哪个服务(函数)的名字
uint32_t svcmgr = BINDER_SERVICE_MANAGER;
svcmgr_publish(bs, svcmgr, argv[1], &token);
其中target=BINDER_SERVICE_MANAGER = 0 = servicemanager;向服务端发送消息
3.while(true) 3.1:读驱动
int binder_call(struct binder_state *bs,
struct binder_io *msg, struct binder_io *reply,
uint32_t target, uint32_t code)
{
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;
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);
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;
}
for(;;)死循环, res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); 读驱动里面的数据
3.2:解析数据,调用对应的函数
res = binder_parse(bs, reply, (uintptr_t) readbuf, bwr.read_consumed, 0); 解析数据
binder_call分析
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];
if (msg->flags & BIO_F_OVERFLOW) {
fprintf(stderr,"binder: txn buffer overflow\n");
goto fail;
}
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;
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);
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;
}
远程调用:
首先向谁发数据 —→ target=目标进程
调用哪个函数 ——>code = 目标进程函数的id
提供什么参数 ——> msg
返回值是什么 —→reply
int binder_call(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply, uint32_t target, uint32_t code)
1.构造函数:放在buffer中,用binder_io来描述;
2.调用ioctl发送数据;