Android Binder机制之 ServiceManager的启动
Android Binder机制的ServiceManager
对于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的世界。
未完,待续。。。
更多相关文章
- C语言函数以及函数的使用
- 《Android开发艺术探索》第十章Android的消息机制+第十一章Andro
- 理解Android回调函数
- 《Android Dev Guide》系列教程5:Android进程和线程
- Android 消息处理机制(Looper、Handler、MessageQueue,Message)
- Android 消息机制
- Android结束进程的方法
- Android触摸事件分发机制详解