简介
- servicemanager 进程
- 主要任务是什么?
- 实现机制;
。启动流程
servicemanager 是一个可执行程序,由于起优先级很高,所以在init进程起来后,很快会被fork出来,下面是servicemanager进程的启动配置:
service servicemanager /system/bin/servicemanager
class core ->声明为core类型进程,将最先被init进程fork出来执行.
user system
group system readproc -> 什么服务所在进程组和相关权限
critical -> 声明为关键进程,若死掉次数超过4次,将会触发linux kernel重启
onrestart restart healthd
onrestart restart zygote
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver ->上面这些重要的进程的启动需要依赖servicemanager进程
writepid /dev/cpuset/system-background/tasks
所以可以看出,servicemanager进程在init进程起来后会以最高优先级启动,因为很多重要的进程,比如zygote、surfaceflinger、media等都需要依赖它的存在,若servicemanager进程启动异常,显然Android系统是启动不了的。 这里简单介绍了servicemanager的启动优先级以及一些进程依赖关系,下面重点看下它启动后具体干了什么事情。
源码路径:
frameworks$ find ./ -name service_manager.c
./native/cmds/servicemanager/service_manager.c
首先看main函数实现:
int main()
{
struct binder_state *bs;
/* Open /dev/binder设备,使用mmap映射一块128kb的内存与之关联,
内核中对应的操作是为 struct binder_proc *proc; 结构实例申请内存,初始化赋值当前进程等操作,申请size为128kb的虚拟内存,添加到虚拟内存管理数据结构中.
*/
bs = binder_open(128*1024);
if (!bs) {
ALOGE("failed to open binder driver\n");
return -1;
}
/* 下发BINDER_SET_CONTEXT_MGR的command,声明为binder上下文管理,内核中对应结构是:struct binder_node *binder_context_mgr_node; */
if (binder_become_context_manager(bs)) {
ALOGE("cannot become context manager (%s)\n", strerror(errno));
return -1;
}
... /* 略过selinux相关检查 */
/* 进入for(;;)轮询,不断从binder驱动中获取解析cmd数据,若cmd
是 BR_TRANSACTION 类型,则回调 svcmgr_handler 函数,该函数主要实现的功能
主要是:ADD,GET,CHECK,LIST 服务等操作,新ADD的服务最终会通过do_add_service函数接口添加到svcinfo *svclist 数据结构实例中使用链表管理起来,以便实现GET,CHECK,LIST service等操作,系统服务只有注册到servicemanager的这个svclist中才能够实现被统一管理.
*/
binder_loop(bs, svcmgr_handler);
return 0;
}
需要注意的一点是,所有的这些ADD/GET service都是封装后的数据,属于binder的一套协议,svcinfo 结构如下:
struct svcinfo
{
struct svcinfo *next;
uint32_t handle;
struct binder_death death;
int allow_isolated;
size_t len;
uint16_t name[0]; -> 保存service的name,而实际通过binder 驱动传输数据过程是传输一个uint16_t类型数据.
};
初始化主流程图:servicemanager初始化小结:
。打开/dev/binder设备,kernel对应操作就是初始化binder_proc数据结构实例;
。使用mmap系统调用建立一块128k的虚拟内存映射到binder驱动;
。声明binder上下文管理守护进程,kernel对应的就是初始化binder_context_mgr_node结构;
。进入binder消息轮询,等待client消息到来;
现在有个问题,上面初始化完成后,是如何工作的呢?也就是消息轮询是怎么做的呢?下面以add service这个消息来简单梳理下工作流程.
先看binder_loop的实现:
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
uint32_t readbuf[32];
...
/* ioctl 知会binder驱动开始进入looper */
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t));
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
/* 从驱动中取出bwr message */
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
...
/* 解析 bwr message */
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
...
}
}
重点是binder_parse函数的实现:
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
int r = 1;
uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end) {
...
case BR_TRANSACTION: {
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
if ((end - ptr) < sizeof(*txn)) {
ALOGE("parse: txn too small!\n");
return -1;
}
binder_dump_txn(txn);
if (func) {
unsigned rdata[256/4];
struct binder_io msg;
struct binder_io reply;
int res;
/* 转换取出binder传输数据到binder io */
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
/* 当解析到cmd=BR_TRANSACTION的时候回调svcmgr_handler 函数 */
res = func(bs, txn, &msg, &reply);
/* ONE_WAY 属于异步类型,所以不需要等待返回结果*/
if (txn->flags & TF_ONE_WAY) {
binder_free_buffer(bs, txn->data.ptr.buffer);
} else {
/* 否则默认同步调用,发送BC_REPLY的CMD到驱动,告知等待返回结果 */
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
}
}
ptr += sizeof(*txn);
break;
}
...
}
return r;
}
再看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;
/* 转换获取service的name */
s = bio_get_string16(msg, &len);
...
switch(txn->code) {
/* getService() || checkService() */
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
/* 查询svclist链表中已有的service */
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);
if (!handle)
break;
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
/* addService() */
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
/* add service 的真正实现,将新的service最终添加
到svclist这个单 链表中管理起来
*/
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
...
/* add service成功,把reply存入bio结构实例中 */
bio_put_uint32(reply, 0);
return 0;
}
add service 流程图:
从图上可以看出在servicemanager里面,add service要做的事情其实也不复杂:
。解析出cmd == BR_TRANSACTION,回调svcmgr_handler函数;
。执行do_add_service动作,将新的svc添加到svclist链表中管理;
。回复消息给binder驱动;
所以servicemanager主要干的事情是:
-
实现所有的系统服务注册管理,所有的系统服务信息保存到全局链表svclist中的维护;
-
作为守护进程,轮询binder驱动(/dev/binder)来实现两个进程间的binder协议数据交互,为binder机制提供服务;