一、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担负起守护进程的职责了。