从四年多的数通开发方向转到Android系统开发方向,的确是一个华丽而艰辛的转身。初识Android时,先从Android的整个系统框架梳理了一遍,让之了然于胸,鉴于对kernel的了解,先从Android新增的Binder驱动相关来入手,尽管Binder理解起来十分生涩,但是如果你认真去分析源码后,会发现其中的奥秘,会惊叹于他设计的巧妙,感叹Google工程师的神奇,所以从这篇开始我要分几篇文章来详细介绍Binder通信。
我们知道,Android系统基于Linux, 而传统的Linux 有消息队列,Pipe, System V , Socket等,Socket传输效率低,开销大,主要用在跨网络的进程间通信和本机上进程间的低速通信, 而消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区,然后再从内核缓存区拷贝到接收方缓存区,至少两次拷贝。而共享内存呢虽然0次拷贝,但安全性不好控制。Binder属于C/S架构,使用了Proxy代理设计模式,整个BInder通信框架可以分为四个角色;Server, Client, Service Manager和Binder驱动,前三个位于User Space, Binder驱动位于kernel Space:客户端通过服务端进程代理对象,发送请求到代理对象,代理对象通过Binder驱动将请求转发给服务端进程处理,处理完成以后server再通过Binder驱动reply代理对象。对于面向对象的BInder IPC, Server必须有确定的访问接入点地址来接手client的请求,以及command-reply协议传输数据。本章我们主要来讲讲Service Manager,这个总管家的内部机制吧。
Service Manager为服务管理着,他负责的任务就是管理提供服务者的列表,比如service的新增、查询、删除等,它存在的意义在于统一管理系统的服务,Android系统某服务的客户端必须通过Service Manager来查询服务信息,再与之交互,我们开始从Service Manager进程的启动开始来分析它的作用。Service Manager是C语言实现的,在Init进程加载Init.rc文件时创建出来的,Init.rc脚本里这么写道:
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart media
onrestart restart surfaceflinger
onrestart restart drm
这段脚本表示servicemanager是一个服务,执行/system/bin/servicemanager下的可执行文件,那我们再看看servicemanager的main函数吧;service_manager.c中:
int main(int argc, char **argv)
{
struct binder_state *bs;
void *svcmgr = BINDER_SERVICE_MANAGER;
bs = binder_open(128*1024);
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
svcmgr_handle = svcmgr;
binder_loop(bs, svcmgr_handler);
return 0;
}
首先定义BINDER_SERVICE_MANAGER是(void*)0,这个是service manager的特定handler,任何发往service manager的targer必须是它,而后binder_open源码如下:
struct binder_state *binder_open(unsigned mapsize)
{
struct binder_state *bs;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return 0;
}
bs->fd = open("/dev/binder", O_RDWR);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open device (%s)\n",
strerror(errno));
goto fail_open;
}
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
if (bs->mapped == MAP_FAILED) {
fprintf(stderr,"binder: cannot map device (%s)\n",
strerror(errno));
goto fail_map;
}
/* TODO: check version */
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return 0;
}
它做个如下几个事情:
1. 给binder_state分配空间,记录binder相关信息
2. 通过系统调用open打开/dev/binder文件,记录文件句柄
3.为活得的binder文件句柄映射128k的内存,
而后binder_become_context_manager就是通知binder驱动,我就是守护进程,最后进入循环等待接受请求的到来。我们注意到这个细节,在binder_loop函数中,要先binder_write一个buffer头为BC_ENTER_LOOPER的buffer后才开始无限循环状态,因为这个BC_ENTER_LOOPER为设置service manager binder thread的looper状态BINDER_LOOPER_STATE_ENTERED的。我们这里注册了一个回调函数svcmgr_handler,代码如下:
int svcmgr_handler(struct binder_state *bs,
struct binder_txn *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
unsigned len;
void *ptr;
uint32_t strict_policy;
int allow_isolated;
if (txn->target != svcmgr_handle)
return -1;
// 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);
s = bio_get_string16(msg, &len);
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\n", str8(s));
return -1;
}
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len, txn->sender_euid);
if (!ptr)
break;
bio_put_ref(reply, ptr);
return 0;
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;
case SVC_MGR_LIST_SERVICES: {
unsigned n = bio_get_uint32(msg);
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
default:
ALOGE("unknown code %d\n", txn->code);
return -1;
}
bio_put_uint32(reply, 0);
return 0;
}
很显然,这个就是service manager的主要任务处理, SVC_MGR_GET_SERVICE, SVC_MGR_CHECK_SERVICE, SVC_MGR_ADD_SERVICE, SVC_MGR_LIST_SERVICES。