注册服务过程:
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;
}
( 未完待续)