一、Service Manager是android系统核心程序,在系统启动后,自动运行,在系统的初始化配置文件init.rc中配置
该文件在out/target/product/generic/root,文件中有如下内容:
service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart zygote onrestart restart media二、 Service Manager的如何成为大内总管的源代码分析
源码位于frameworks\base\cmds\servicemanager\service_manager.c
1、代表Binder设备的结构
struct binder_state { int fd; //设备描述符 void *mapped; //设备内存映射区指针 unsigned mapsize; //内存映射区大小 };2、打开设备
struct binder_state *binder_open(unsigned mapsize) { struct binder_state *bs; //binder设备结构 bs = malloc(sizeof(*bs)); //分配空间 bs->fd = open("/dev/binder", O_RDWR); //打开设备 bs->mapsize = mapsize; //空间大小赋值 bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);//设备文件映射进内存,并返回映射区指针 }3、大内总管申请函数
int binder_become_context_manager(struct binder_state *bs) { //ioctl是binder驱动程序提供的设备控制函数,传递BINDER_SET_CONTEXT_MGR这个参数,告诉驱动,我这个节点要成为管理者 return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0); }4、驱动控制函数ioctl
Binder驱动源代码目录:kernel/goldfish/drivers/staging/android
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
//系统允许多个进程打开binder驱动,都会有一个专门的结构binder_proc管理当前进程的信息,
//包括进程的ID,当前进程由mmap所映射出的buffer信息,以及当前进程所允许的最大线程量。
//同时这个binder_proc会加入到系统的全局链表binder_procs中去,方便在不同进程之间可以查找信息。
struct binder_proc *proc = filp->private_data;//获得了Service Manager进程进程信息
//在当前进程下存在多线程,因此binder驱动使用binder_thread来管理对应的线程信息,
//主要包括线程所属的binder_proc、当前状态looper以及一个transaction_stack(负责着实际进程间通信交互的源头和目的地)
struct binder_thread *thread;
unsigned int size = _IOC_SIZE(cmd);
void __user *ubuf = (void __user *)arg;
//获得了Service Manager线程信息
thread = binder_get_thread(proc);
//处理控制命令
switch (cmd)
{
//读写命令,则进行读写操作
case BINDER_WRITE_READ:
{ ...
break;
}
case BINDER_SET_MAX_THREADS:
break;
//请求成为Service Manager命令
case BINDER_SET_CONTEXT_MGR:
if (binder_context_mgr_node != NULL)
{//已经存在则返回错误
printk(KERN_ERR "binder: BINDER_SET_CONTEXT_MGR already set\n");
}
if (binder_context_mgr_uid != -1)
{//其他的判断
....
}
else
binder_context_mgr_uid = current->cred->euid;//设置Sevice Manager守护进程的uid
//创建一个新的Service Manager实体节点
binder_context_mgr_node = binder_new_node(proc, NULL, NULL);
//添加节点信息
binder_context_mgr_node->local_weak_refs++;
binder_context_mgr_node->local_strong_refs++;
binder_context_mgr_node->has_strong_ref = 1;
binder_context_mgr_node->has_weak_ref = 1;
break;
case BINDER_THREAD_EXIT://线程退出命令
break;
case BINDER_VERSION://版本信息命令
break;
default:
ret = -EINVAL;
goto err;
}
}
5、main函数分析:
int main(int argc, char **argv) { struct binder_state *bs;//binder设备结构 void *svcmgr = BINDER_SERVICE_MANAGER; //服务管理指针 bs = binder_open(128*1024);//打开binder设备,并分配128K的内存映射空间 //申请成为大内总管 if (binder_become_context_manager(bs)) { LOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } //调用binder_loop进入到循环状态,并提供了一个回调函数,等待用户的请求 //用户请求包括,客户端:查询和获取服务;服务端:注册服务 svcmgr_handle = svcmgr; //回调函数指针 //binder消息分发的关键循环,循环等待请求,回调函数svcmgr_handler binder_loop(bs, svcmgr_handler); return 0; }
6、binder_loop函数分析
void binder_loop(struct binder_state *bs, binder_handler func)
{
int res;
struct binder_write_read bwr;
unsigned readbuf[32];
bwr.write_size = 0;
bwr.write_consumed = 0;
bwr.write_buffer = 0;
//通过binder_write函数执行BC_ENTER_LOOPER命令告诉Binder驱动程序, Service Manager要进入循环了
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(unsigned));
for (;;)
{//一直循环下去,为所有service工作
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (unsigned) readbuf;
// 一般阻塞再此,直到有消息送达,等待有客户端的通过binder驱动的请求
//与binder驱动对话,先写再读,不过这里写的size为0(bwr.write_size = 0),所以这里是只读binder端的数据
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
//分析读回来的数据,记住这里的func传入的参数是svcmgr_handler
res = binder_parse(bs, 0, readbuf, bwr.read_consumed, func); }}
我们再看binder_parse(bs, 0, readbuf, bwr.read_consumed, func):
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); //循环解析由binder驱动传递过来的命令 while (ptr < end) { //循环取得一个命令 uint32_t cmd = *ptr++; //对各种命令进行处理 switch(cmd) { case BR_NOOP: break; case BR_TRANSACTION_COMPLETE: break; case BR_INCREFS: case BR_ACQUIRE: case BR_RELEASE: case BR_DECREFS: //当是这个命令时,调用回调函数svcmgr_handler case BR_TRANSACTION: { struct binder_txn *txn = (void *) ptr; binder_dump_txn(txn); if (func) { 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; } ... } } return r; }
三、服务器程序如何向Service Manager注册服务
当server向binder设备写入请求注册Service时,main函数中的binder_loop循环,会获取到该server程序通过binder驱动发来的请求,通过解析binder_parse函数调用回调函数svrmgr_handle,这个函数是服务管理器各种请求的处理函数,看下这个函数:
int svcmgr_handler(struct binder_state *bs, struct binder_txn *txn, struct binder_io *msg, struct binder_io *reply) { //省略部分代码 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); 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); //调用添加服务函数 if (do_add_service(bs, s, len, ptr, txn->sender_euid)) return -1; break; //服务列表 case SVC_MGR_LIST_SERVICES: { unsigned n = bio_get_uint32(msg); si = svclist; while ((n-- > 0) && si) si = si->next; } } }服务器的注册,通过do_add_service函数来实现, 我们仔细看看do_add_service函数的实现:
int do_add_service(struct binder_state *bs, uint16_t *s, unsigned len, void *ptr, unsigned uid) { struct svcinfo *si;//要注册的service信息结构 //首先检查是否有权限注册service,没权限就对不起了,出错返回 if (!svc_can_register(uid, s)) //根据进程的uid来判断是否是服务 { return -1; } //然后检查是否已经注册过,注册过的service将不能再次注册 si = find_svc(s, len); if (si) { if (si->ptr) { svcinfo_death(bs, si); } si->ptr = ptr; } else //否则的话可以进行注册 { //然后构造一个svcinfo对象,并加入一个全局链表中svclist中 si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t)); si->ptr = ptr; si->len = len; memcpy(si->name, s, (len + 1) * sizeof(uint16_t)); si->name[len] = '\0'; si->death.func = svcinfo_death; si->death.ptr = si; si->next = svclist; svclist = si; } //最后通知binder设备:有一个service注册进来 binder_acquire(bs, ptr); binder_link_to_death(bs, ptr, &si->death); return 0; }
四、客户端程序如何获取服务
当客户端程序向binder设备写入查询service的请求后,main函数中的binder_loop循环,会获取到该client程序通过binder驱动发来的请求,通过解析binder_parse函数调用回调函数svrmgr_handle,回调函数中有如下代码:
//查询获取服务
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
ptr = do_find_service(bs, s, len);
if (!ptr)
break;
//如果查找到的话,写入reply中返回给客户端
bio_put_ref(reply, ptr);
return 0;
通过do_find_service函数,查询获取服务,代码如下:
void *do_find_service(struct binder_state *bs, uint16_t *s, unsigned len) { struct svcinfo *si; si = find_svc(s, len); if (si && si->ptr) { return si->ptr; } else { return 0; } }
总结:
Service Manager是成为守护进程的过程是这样的:
1. 打开/dev/binder文件:open("/dev/binder", O_RDWR);
2. 建立128K内存映射:mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
3. 通知Binder驱动程序它是守护进程:binder_become_context_manager(bs);
4. 进入循环等待请求的到来:binder_loop(bs, svcmgr_handler);
在这个过程中,在Binder驱动程序中建立了一个struct binder_proc结构、一个struct binder_thread结构和一个struct binder_node结构,这样,Service Manager就在Android系统的进程间通信机制Binder担负起守护进程的职责了。