注册服务过程:
1. 打开binder设备驱动
2. 发布服务,看代码
int svcmgr_publish(struct binder_state *bs, void *target, const char *name, void *ptr) { unsigned 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; }1) 首先进行了数据封装, msg中放的是发给目标进程的数据,首先放入一个整数0,接着放入SVC_MGR_NAME,要发布的服务名name,和ptr
来看结构体 struct binder_io
struct binder_io { char *data; /* pointer to read/write from */ uint32_t *offs; /* array of offsets */ uint32_t data_avail; /* bytes available in data buffer */ uint32_t offs_avail; /* entries available in offsets array */ char *data0; /* start of data buffer */ uint32_t *offs0; /* start of offsets buffer */ uint32_t flags; uint32_t unused; };binder_io管理一段内存,data 指向data buffer的首个可用字节, data0 指向data buffer的起始地址。
offs 指向 offsets array中首个可用的 uint32_t * 类型的地址, offs0 指向offsets array中首个可用的起始地址
data_avail 为 可用的 data buffer 字节数, offs_avail为可用的 offs array中的 字节数/sizeof(uint32_t)
unsigned iodata[512/4]; bio_init(&msg, iodata, sizeof(iodata), 4);
来看bio_init
void bio_init(struct binder_io *bio, void *data, uint32_t maxdata, uint32_t maxoffs) { uint32_t n = maxoffs * sizeof(uint32_t); // n 为 offsets array占用的字节数 if (n > maxdata) { // n 大于 iodata 的总字节 bio->flags = BIO_F_OVERFLOW; // 标志设为 OVER_FLOW bio->data_avail = 0; bio->offs_avail = 0; return; } bio->data = bio->data0 = (char *) data + n; // data buffer 的起始地址设置 bio->offs = bio->offs0 = data; // offs array 的起始地址 bio->data_avail = maxdata - n; // 目前可用 data buffer字节数 bio->offs_avail = maxoffs; // off array中可用的数目 bio->flags = 0; }
来看bio_put_uint32
bio_put_uint32(&msg, 0); // strict mode header
void bio_put_uint32(struct binder_io *bio, uint32_t n) { uint32_t *ptr = bio_alloc(bio, sizeof(n)); if (ptr) *ptr = n; }
来看 bio_alloc
static void *bio_alloc(struct binder_io *bio, uint32_t size) { size = (size + 3) & (~3); if (size > bio->data_avail) { bio->flags |= BIO_F_OVERFLOW; return 0; } else { void *ptr = bio->data; bio->data += size; bio->data_avail -= size; return ptr; } }size = (size + 3) & (~3);// size 校准
作用: 使 4*n < size <= 4*(n+1) 时, size = 4*(n+1); n为整数
例如, size = 3, 校准后 size 为 4; size = 13, 校准后 16
看起来,bio_alloc 以 4个字节为单位划分data buffer。
bio_alloc 只是在 data buffer 中 准备需要的内存。
接下来看:
bio_put_string16_x(&msg, name);
void bio_put_string16_x(struct binder_io *bio, const char *_str) { unsigned char *str = (unsigned char*) _str; uint32_t len; uint16_t *ptr; if (!str) { bio_put_uint32(bio, 0xffffffff); return; } len = strlen(_str); if (len >= (MAX_BIO_SIZE / sizeof(uint16_t))) { bio_put_uint32(bio, 0xffffffff); return; } bio_put_uint32(bio, len); // 首先将 字符串的长度放入 buffer中 ptr = bio_alloc(bio, (len + 1) * sizeof(uint16_t)); // 准备 空间 if (!ptr) return; while (*str) / / 将字符串的内容复制到 data buffer 空间中
*ptr++ = *str++;* ptr++ = 0 ;}
2) 调用binder_call,来看源码
int binder_call(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply, void *target, uint32_t code) { int res; struct binder_write_read bwr; struct { uint32_t cmd; struct binder_txn txn; } 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 = target; writebuf.txn.code = code; writebuf.txn.flags = 0; writebuf.txn.data_size = msg->data - msg->data0; writebuf.txn.offs_size = ((char*) msg->offs) - ((char*) msg->offs0); writebuf.txn.data = msg->data0; writebuf.txn.offs = msg->offs0; bwr.write_size = sizeof(writebuf); bwr.write_consumed = 0; bwr.write_buffer = (unsigned) &writebuf; hexdump(msg->data0, msg->data - msg->data0); for (;;) { bwr.read_size = sizeof(readbuf); bwr.read_consumed = 0; bwr.read_buffer = (unsigned) 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, 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; }
来看 binder_write_read
struct binder_write_read { signed long write_size; // write_buffer 中的字节数 signed long write_consumed; unsigned long write_buffer; // write_buffer 的地址 signed long read_size; // read_buffer 中的字节数 signed long read_consumed; unsigned long read_buffer; // read_buffer 的地址 };
来看 binder_txn 结构体
struct binder_txn { void *target; // target 指向了目标服务 void *cookie; uint32_t code; // code 指向了具体该调用的函数 uint32_t flags; uint32_t sender_pid; uint32_t sender_euid; uint32_t data_size; // data buffer 已写的字节数 uint32_t offs_size; // offsets array 中已写的字节数 void *data; // data buffer 起始地址 void *offs; // offsets array 起始地址 };
来看函数
void bio_init_from_txn(struct binder_io *bio, struct binder_txn *txn) { bio->data = bio->data0 = txn->data; //data的位置指向了data buffer的开始 bio->offs = bio->offs0 = txn->offs; bio->data_avail = txn->data_size; bio->offs_avail = txn->offs_size / 4; bio->flags = BIO_F_SHARED; }
调用binder_parse
res = binder_parse(bs, reply, readbuf, bwr.read_consumed, 0);正确的话会执行:
case BR_REPLY: { struct binder_txn *txn = (void*) ptr; if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) { ALOGE("parse: reply too small!\n"); return -1; } binder_dump_txn(txn); if (bio) { bio_init_from_txn(bio, txn); // 从txn中 bio = 0; } else { /* todo FREE BUFFER */ } ptr += (sizeof(*txn) / sizeof(uint32_t)); r = 0; break; }
reply->data 为内核分配的一段内存,存放了被调用者的返回
status = bio_get_uint32(&reply);拿到返回值
binder_done(bs, &msg, &reply);
void binder_done(struct binder_state *bs, struct binder_io *msg, struct binder_io *reply) { if (reply->flags & BIO_F_SHARED) { uint32_t cmd[2]; cmd[0] = BC_FREE_BUFFER; cmd[1] = (uint32_t) reply->data0; binder_write(bs, cmd, sizeof(cmd)); reply->flags = 0; } }
释放掉 reply->data0 指向的内存
接下来来看,注册服务的具体内容:
最终调用了 svcmgr_handler 函数
int svcmgr_handler(struct binder_state *bs, struct binder_txn *txn, struct binder_io *msg, struct binder_io *reply)的
case SVC_MGR_ADD_SERVICE: s = bio_get_string16(msg, &len); ptr = bio_get_ref(msg); allow_isolated = bio_get_uint32(msg) ? 1 : 0; if (do_add_service(bs, s, len, ptr, txn->sender_euid, allow_isolated)) return -1; break;
来看 do_add_service
int do_add_service(struct binder_state *bs, uint16_t *s, unsigned len, void *ptr, unsigned uid, int allow_isolated) { struct svcinfo *si; //ALOGI("add_service('%s',%p,%s) uid=%d\n", str8(s), ptr, // allow_isolated ? "allow_isolated" : "!allow_isolated", uid); if (!ptr || (len == 0) || (len > 127)) return -1;
// 判读调用者有没有权限 if (!svc_can_register(uid, s)) {ALOGE( "add_service('%s',%p) uid=%d - PERMISSION DENIED \n " , str8( s) , ptr , uid) ; return - 1 ; }
// 查找服务
si =
find_svc(
s
,
len)
;
if (si) { //找到服务
if (si->
ptr) {
ALOGE(
"add_service('%s',%p) uid=%d - ALREADY REGISTERED, OVERRIDE
\n
"
,
str8(
s)
,
ptr
,
uid)
;
svcinfo_death(
bs
, si)
;
} si->
ptr =
ptr
;
}
else { si =
malloc(
sizeof(*si) + (
len +
1) *
sizeof(
uint16_t))
; // 分配一个svcinfo 结构体和 name 的空间
if (!si) {
ALOGE(
"add_service('%s',%p) uid=%d - OUT OF MEMORY
\n
"
,
str8(
s)
,
ptr
,
uid)
;
return -
1
;
} si->
ptr =
ptr
; // service 的函数地址写入
si->
len =
len
;
memcpy(si->
name
,
s
, (
len +
1) *
sizeof(
uint16_t))
;
si->
name[
len] =
'
\0
'
;
si->
death.
func =
svcinfo_death
;
si->
death.
ptr = si
;
si->
allow_isolated =
allow_isolated
;
si->
next =
svclist
; // 将服务添加到 svclist 链表中
svclist = si
;
}
binder_acquire(
bs
,
ptr)
;
binder_link_to_death(
bs
,
ptr
, &si->
death)
;
return
0
;}
来看 find_svc
struct svcinfo *find_svc(uint16_t *s16, unsigned len) { struct svcinfo *si; for (si = svclist; si; si = si->next) { if ((len == si->len) && !memcmp(s16, si->name, len * sizeof(uint16_t))) { return si; } } return 0; }
( 未完待续)