对于Android 来说,Binder进程间的通信机制几乎无处不在,可以说是整个Android系统中各个组件之间交互的灵魂。所以,想要深入的理解Android 中进程间通信的机制,还是需要对Binder机制有一个深入的研究的。
Binder机制很复杂,设计到的东西特别多,很难一下将这些东西说清楚,到期该从何说起呢?不防就从Binder服务的管理者ServiceManger开始说起吧。
servicemanager是一个独立的进程,在Android系统启动的时候有init.rc脚本,启动脚本如下:
service servicemanager /system/bin/servicemanager
class core
user system
group system
critical
onerestart zygote
onerestart media
onerestart surfaceflinger
...
有必要对上面的启动脚本进行解释一下子:
service servicemanager 表示该进程是以服务的形式运行的
class core 表示这个是核心服务
critical 表示很重要
onerestart zygote 表示该服务重启,需要重启zygote进程(后面的含义是一样的)。
Android 系统启动servicemanager之后,是让它不停地干活的,具体干什么活呢?既然是名字叫做ServiceManager,那么它既是用来管理系统service的,具体来说有两个功能1. addService ,即注册一个服务到系统中 2. getService,即返回服务的代理对象。对于这个两个功能的实现,且看servicemanager的main函数
代码路径为:frameworks/base/cmds/servicemanager/service_manager.c
int main(int argc, char **argv)
{
struct binder_state *bs; //ServiceManager的描述
bs = binder_open(128*1024); //关键点1
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
if (binder_become_context_manager(bs)) { //关键点2
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
... //中间为selinux相关代码, 和主题无关
//进入Binder 的loop中
binder_loop(bs, svcmgr_handler); //关键点3
return 0;
}
对于main函数中标记的关键点做出解释:
1. binder_open:
总的来说binder_open 干了三件事情:1. 打开/dev/binder 获得句柄值 2. 通过ioctl 查询Binder版本 3.映射地址空间
且看源码:
struct binder_state *binder_open(size_t mapsize)
{
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
//1. 打开驱动
bs->fd = open("/dev/binder", O_RDWR);
if (bs->fd < 0) {
fprintf(stderr,"binder: cannot open device (%s)\n",
strerror(errno));
goto fail_open;
}
//2. ioctl
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
fprintf(stderr,
"binder: kernel driver version (%d) differs from user space version (%d)\n",
vers.protocol_version, BINDER_CURRENT_PROTOCOL_VERSION);
goto fail_open;
}
//通过mmap将空间映射到用户空间
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;
}
return bs;
fail_map:
close(bs->fd);
fail_open:
free(bs);
return NULL;
}
2. binder_become_context_manager
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
上面代码比较明显,即是通过ioctl来让servicemanger成为服务管理中心,并设置handle为0(这个0很重要,后续分析)
3. binder_loop
servicemanager将在这里完成系统交给它的使命:对service进行注册和返回其代理对象。
binder_loop(bs, svcmgr_handler); //bs携带者servicemanager的信息,svcmgr_handler则是一个回调函数
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t)); //告知binder驱动,servicemanager进入loop循环
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr); //从binder驱动中读取数据
if (res < 0) {
ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno));
break;
}
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func); //解析数据,并传递func回调函数
if (res == 0) {
ALOGE("binder_loop: unexpected reply?!\n");
break;
}
if (res < 0) {
ALOGE("binder_loop: io error %d %s\n", res, strerror(errno));
break;
}
}
}
上面的binder_loop循环会不断的通过ioctl从binder驱动中读取数据,并解析执行。在binder_parse中会解析出从binder驱动中读取的命令,然后通过servicemanager中注册的回调函数svcmgr_handler来执行具体的指令
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;
int allow_isolated;
//一些条件判定的逻辑操作,这里省略
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE: //Client组件请求获取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); //执行getService操作
if (!handle)
break;
bio_put_ref(reply, handle); //将handle写入驱动
return 0;
case SVC_MGR_ADD_SERVICE: //Service请求注册到ServiceManager中
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, //执行addService的操作
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: { //查询所有的service操作
uint32_t n = bio_get_uint32(msg);
if (!svc_can_list(txn->sender_pid)) {
ALOGE("list_service() uid=%d - PERMISSION DENIED\n",
txn->sender_euid);
return -1;
}
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;
}
首先看addService的请求操作
int do_add_service(struct binder_state *bs,
const uint16_t *s, size_t len,
uint32_t handle, uid_t uid, int allow_isolated,
pid_t spid)
{//servicemanager中通过一个链表来维护所有注册进来的service组件
struct svcinfo *si; //svcinfo 是service链表的一个节点
//ALOGI("add_service('%s',%x,%s) uid=%d\n", str8(s, len), handle,
// allow_isolated ? "allow_isolated" : "!allow_isolated", uid);
if (!handle || (len == 0) || (len > 127))
return -1;
if (!svc_can_register(s, len, spid, uid)) { //检测该service是否可以进行注册到ServiceManager
ALOGE("add_service('%s',%x) uid=%d - PERMISSION DENIED\n",
str8(s, len), handle, uid);
return -1;
}
si = find_svc(s, len);
if (si) { //如果已经注册了,将不再注册
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else { //开始将service注册到ServiceManager中
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + 1) * sizeof(uint16_t));
si->name[len] = '\0';
si->death.func = (void*) svcinfo_death;
si->death.ptr = si;
si->allow_isolated = allow_isolated;
si->next = svclist;
svclist = si;
}
binder_acquire(bs, handle); //将service注册到binder驱动中, 通过binder_write 将命令写入binder驱动
binder_link_to_death(bs, handle, &si->death);
return 0;
}
getService和addService很相似,这里就不再贴代码了。 getService时也是通过查询ServiceManager维护的链表,然后返回其handle。好像getService时没有和binder驱动进行交互(但是binder驱动的引用计数和这个也关系的)。
到这里ServiceManager进行的启动大的大致过程讲完了,但是这里还有很多细节问题的问题是没有说到的。亲爱的读者,你有没有发现,ServiceManager进程确实是实现了对service组件的管理,ServiceManager进程现在还没有提供任何进行addService和getService的接口。在Native层要注册addService或者getSerivce是通过IServiceManager接口进行的,IServiceManager接口到底是怎么和servicemanager进程之间建立联系的。以及,当前仅仅介绍了servicemanager进程启动,还没有真正的进入binder的世界。
未完,待续。。。