1.打开驱动
//frameworks\native\cmds\servicemanager\bctest.c
int main(int argc, char **argv)
{
int fd;
struct binder_state *bs;
uint32_t svcmgr = BINDER_SERVICE_MANAGER;
uint32_t handle;
bs = binder_open(128*1024); //打开驱动
if (!bs) {
fprintf(stderr, "failed to open binder driver\n");
return -1;
}
//省略其他代码
return 0;
}
2.注册服务
调用binder_call
各个参数:
- bs:打开驱动的句柄
- msg:包含要注册的服务的名字
- reply:回复的内容
- target:这里是BINDER_SERVICE_MANAGER
- SVC_MGR_ADD_SERVICE:表示要注册服务
//frameworks\native\cmds\servicemanager\bctest.c
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);
//bs:打开驱动的句柄
//msg:包含要注册的服务的名字
//reply:回复的内容
//target:这里是BINDER_SERVICE_MANAGER
//SVC_MGR_ADD_SERVICE:表示要注册服务
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;
}
3.查找服务
调用binder_call
各个参数:
- bs:打开驱动的句柄
- msg:包含要查找的服务的名字
- reply:回复的内容
- target:这里是BINDER_SERVICE_MANAGER
- SVC_MGR_CHECK_SERVICE:表示要查找服务
//frameworks\native\cmds\servicemanager\bctest.c
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
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);
//bs:打开驱动的句柄
//msg:包含要查找的服务的名字
//reply:回复的内容
//target:这里是BINDER_SERVICE_MANAGER
//SVC_MGR_CHECK_SERVICE:表示要查找服务
if (binder_call(bs, &msg, &reply, target, SVC_MGR_CHECK_SERVICE))
return 0;
handle = bio_get_ref(&reply);
if (handle)
binder_acquire(bs, handle);
binder_done(bs, &msg, &reply);
return handle;
}
4.binder_call方法
- 将msg、target、code构造成ioctl的参数bwr
- 调用ioctl函数
//frameworks\native\cmds\servicemanager\binder.c
//bs:
//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)
{
int res;
struct binder_write_read bwr; //ioctl函数需要的参数是binder_write_read
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;
}
//将target、code、msg 构建给bwr
writebuf.cmd = BC_TRANSACTION;
writebuf.txn.target.handle = target; //target
writebuf.txn.code = code; //code
writebuf.txn.flags = 0;
writebuf.txn.data_size = msg->data - msg->data0; //msg的数据
writebuf.txn.offsets_size = ((char*) msg->offs) - ((char*) msg->offs0); //msg的数据
writebuf.txn.data.ptr.buffer = (uintptr_t)msg->data0; //msg的数据
writebuf.txn.data.ptr.offsets = (uintptr_t)msg->offs0; //msg的数据
bwr.write_size = sizeof(writebuf);
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) &writebuf; //将刚刚的writebuf赋值给bwr的write_buffer
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); //调用ioctl
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;
}
5.client
(韦老师的视频截图)
6.server
(韦老师视频截图)