简介
ServiceManager功能相当于所有服务(Service)的一个管理器,是一个标准的Binder Service。
ServiceManager的启动
ServiceManager是通过init.rc(\system\core\rootdir\init.rc)启动的。
在init.rc中相关代码:
service servicemanager /system/bin/servicemanager àservice(指令,可执行程序) <name><pathname> class core àclass<name>为服务指定一个名,统一class的所有服务必须同启同停 user system àuser<username>在启动服务前将用户切换至<username>,默认root group systemàgroup<groupname>在启动服务前将用户组切换至<groupname> critical à表明对设备至关重要的一个服务,四分钟退出超过四次,设备将重启进入恢复模式 onrestart restart healthdàonrestart标识重启时执行某些命令 onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm |
ServiceManager是用C/C++编写的,源码路径在:\frameworks\native\cmds\servicemanager\ service_manager.c
相关的make(\frameworks\native\cmds\servicemanager\Android.mk)文件如下:
LOCAL_PATH:= $(call my-dir) #include $(CLEAR_VARS) #LOCAL_SRC_FILES := bctest.c binder.c #LOCAL_MODULE := bctest #include $(BUILD_EXECUTABLE) include $(CLEAR_VARS) LOCAL_SHARED_LIBRARIES := liblog LOCAL_SRC_FILES := service_manager.c binder.cà相关的源文件 LOCAL_MODULE := servicemanager à生成可执行文件 include $(BUILD_EXECUTABLE)à指向一个编译脚本,收集自从上次调用 include $(CLEAR_VARS) 后的所有LOCAL_XXX信息。并决定如何将你列出的Source编译成一个可执行Native程序。 |
ServiceManager启动的工作:
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)) {à设置为Binder管家,整个系统仅此一处 ALOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } svcmgr_handle = svcmgr; binder_loop(bs, svcmgr_handler); return 0; } |
首先给变量svcmgr赋初值,宏定义如下:
/* \frameworks\native\cmds\servicemanager\binder.h */
/* the one magic object */
#define BINDER_SERVICE_MANAGER ((void*) 0)
接下来调用binder_open打开Binder设备,相关源码如下:
/* \frameworks\native\cmds\servicemanager\binder.c */
struct binder_state *binder_open(unsigned mapsize) { struct binder_state *bs;à结构体记录ServiceManager中Binder相关信息,如fd、map大小等 bs = malloc(sizeof(*bs)); if (!bs) { errno = ENOMEM; return 0; }
bs->fd = open("/dev/binder", O_RDWR);à打开Binder驱动节点 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; }
|
mmap()系统调用使得进程之间通过映射同一个普通文件实现共享内存,对于应用程序而言,它通过mmap返回值得到一个内存(当然这是虚拟地址),这个地址通过虚拟内存转换(分段、分页)后最终指向物理内存的某个位置。
此处通过mmap的调用实现了以下目的:
由Binder驱动决定被映射到进程空间中的内存起始地址;
映射区块大小为128K
映射区只读
映射区的改变是私有的,不需要保存文件
从文件的起始地址开始映射
接下来的步骤是将ServiceManager注册成为Binder机制“管家”:
/* \frameworks\native\cmds\servicemanager\binder.c */
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
通过ioctl指令函数发送BINDER_SET_CONTEXT_MGR指令,完成注册。
准备工作就绪,接下来,ServiceManager开始等待客户端的请求,binder_loop(bs, svcmgr_handler);。
/* \frameworks\native\cmds\servicemanager\binder.c */
void binder_loop(struct binder_state *bs, binder_handler func) { int res; struct binder_write_read bwr;à执行BINDER_WRITE_READ指令所需的数据结构 unsigned readbuf[32];à一次读取容量
bwr.write_size = 0; bwr.write_consumed = 0; bwr.write_buffer = 0; readbuf[0] = BC_ENTER_LOOPER;à BC_REGISTER_LOOPER通知 驱动线程池中一个线程已经创建了;BC_ENTER_LOOPER通知驱动该线程已经进入主循环,可以接收数据;BC_EXIT_LOOPER通知驱动该 线程退出主循环,不再接收数据。(待看) binder_write(bs, readbuf, sizeof(unsigned));à把BC_ENTER_LOOPER写入Binder驱动
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) { ALOGE("binder_loop: ioctl failed (%s)\n", strerror(errno)); break; }
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, 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; } } } |
随后ServiceManager进入循环中,和典型的基于事件驱动的程序框架类似,进入循环后做的主要工作如下:
从消息队列中读取消息
如果消息是退出指令,则结束循环;如果消息为空,则继续读取或等待后再读取;如果消息可以运行,则执行指令。
如此循环直到退出
指令的解析和执行是通过binder_parse函数完成的。
/* \frameworks\native\cmds\servicemanager\binder.c */
int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func) { int r = 1; uint32_t *end = ptr + (size / 4);à一个uint32_t占用4个字节 while (ptr < end) { uint32_t cmd = *ptr++;à一个cmd占用一个uint32_t,获取后跳过 #if TRACE fprintf(stderr,"%s:\n", cmd_name(cmd)); #endif switch(cmd) { case BR_NOOP:à 操作完成 break; case BR_TRANSACTION_COMPLETE:à 发送方通过BC_TRANSACTION或BC_REPLY发送完一个数据包后,都能收到该消息做为成功发送的反馈。这和BR_REPLY不一样, 是驱动告知发送方已经发送成功,而不是接收方返回请求数据。所以不管同步还是异步交互接收方都能获得本消息。 break; case BR_INCREFS:à BR_INCREFS/BR_ACQUIRE/BR_RELEASE/BR_DECREFS这一组消息用于管理强/弱指针的引用计数。只有提供Binder实体的进程才能收到这组消息 case BR_ACQUIRE: case BR_RELEASE: case BR_DECREFS: #if TRACE fprintf(stderr," %08x %08x\n", ptr[0], ptr[1]); #endif ptr += 2; break; case BR_TRANSACTION: {à这两条消息分别对应发送方的BC_TRANSACTION和BC_REPLY,表示当前接收的数据是请求或是回复。 struct binder_txn *txn = (void *) ptr; if ((end - ptr) * sizeof(uint32_t) < sizeof(struct binder_txn)) { ALOGE("parse: txn too small!\n"); return -1; } binder_dump_txn(txn);àdump追踪 if (func) {à这个函数为svcmgr_handler() unsigned rdata[256/4]; struct binder_io msg; struct binder_io reply; int res; bio_init(&reply, rdata, sizeof(rdata), 4); bio_init_from_txn(&msg, txn); res = func(bs, txn, &msg, &reply);à具体的消息处理函数 binder_send_reply(bs, &reply, txn->data, res);à回应消息处理结果 } ptr += sizeof(*txn) / sizeof(uint32_t);à处理完成,跳过这一段数据 break; } 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); bio = 0; } else { /* todo FREE BUFFER */ } ptr += (sizeof(*txn) / sizeof(uint32_t)); à处理完成,跳过这一段数据 r = 0; break; } case BR_DEAD_BINDER: { struct binder_death *death = (void*) *ptr++; death->func(bs, death->ptr); break; } case BR_FAILED_REPLY: r = -1; break; case BR_DEAD_REPLY: r = -1; break; default: ALOGE("parse: OOPS %d\n", cmd); return -1; } } return r; } |
BR_TRANSACTION消息:
BR_TRANSACTION消息的处理主要是通过func(svcmgr_handler函数)完成的,主要完成以下功能:
注册:当一个Binder Server创建后,它们要将自己的[名称,Binder句柄]对应关系告知ServiceManager进行备案。
查询:应用程序可以向ServiceManager发起查询请求,以获知某个Binder Service所对应的句柄。
其他信息查询:如ServiceManager版本号、当前状态等。
/* \frameworks\native\cmds\servicemanager\service_manager.c */
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;
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; }àbio_XX系列函数为取出各种类型的数据提供了便利
switch(txn->code) { case SVC_MGR_GET_SERVICE:à以下两个指令是一样的,都是根据Server查找handle值 case SVC_MGR_CHECK_SERVICE: s = bio_get_string16(msg, &len); ptr = do_find_service(bs, s, len, txn->sender_euid);à这个函数执行查找操作,ServiceManager中维护一个全局的svc list变量,用于保存所有server的注册信息。 if (!ptr) break; bio_put_ref(reply, ptr); return 0;
case SVC_MGR_ADD_SERVICE:à用于注册一个Binder Server 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: {à获取列表中的对应server unsigned n = bio_get_uint32(msg);
si = svclist;à所有server信息保存在这个list中 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; } |