Android Framework实战课程-binder专题之ServiceManager启动及运行篇
Posted learnframework
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android Framework实战课程-binder专题之ServiceManager启动及运行篇相关的知识,希望对你有一定的参考价值。
csdn在线学习课程,课程咨询答疑和新课信息:QQ交流群:422901085进行课程讨论
目标:
1、理解servicemanager的dns角色含义
2、源码层面理解servicemanager做了什么
路径:frameworks/native/cmds/servicemanager/servicemanager.rc
service servicemanager /system/bin/servicemanager
class core animation
user system
group system readproc
critical
onrestart restart healthd
onrestart restart zygote
onrestart restart audioserver
onrestart restart media
onrestart restart surfaceflinger
onrestart restart inputflinger
onrestart restart drm
onrestart restart cameraserver
writepid /dev/cpuset/system-background/tasks
shutdown critical
再查看对应代码:
路径:frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char** argv)
{
struct binder_state *bs;
union selinux_callback cb;
char *driver;
if (argc > 1) {
driver = argv[1];
} else {
driver = "/dev/binder";
}
bs = binder_open(driver, 128*1024);//打开驱动
..省略
if (binder_become_context_manager(bs)) {//把自己成为servicemanager
ALOGE("cannot become context manager (%s)\\n", strerror(errno));
return -1;
}
...省略
if (sehandle == NULL) {
ALOGE("SELinux: Failed to acquire sehandle. Aborting.\\n");
abort();
}
if (getcon(&service_manager_context) != 0) {
ALOGE("SELinux: Failed to acquire service_manager context. Aborting.\\n");
abort();
}
binder_loop(bs, svcmgr_handler);//进入循环
return 0;
}
主要有以下几个过程:
1、open binder驱动,并申请对应内存
2、与binder驱动通信成为manager(dns服务器), binder_become_context_manager
3、binder_loop进入接受binder消息事务的循环
binder_open的源码解析如下:
struct binder_state *binder_open(const char* driver, size_t mapsize)
{
。。省略
bs->fd = open(driver, O_RDWR | O_CLOEXEC);//打开驱动
。。省略
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
。。省略
}
bs->mapsize = mapsize;
//映射内存
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
。。省略
}
其中binder_become_context_manager如下:
int binder_become_context_manager(struct binder_state *bs)
{
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
他就是一个很简单的ioctl调用到驱动,让驱动告诉驱动我就是manager,驱动部分暂时不给大家分析
最后是binder_loop(bs, svcmgr_handler)
void binder_loop(struct binder_state *bs, binder_handler func)
{
..省略
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t));//告诉binder驱动,已经进入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驱动中的发送过来的数据
..省略
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
//解析数据,并传入一个svcmgr_handler的函数指针
..省略
}
}
在接下来看binder_parse
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
..省略
while (ptr < end) {
..省略
switch(cmd) {
..省略
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;
bio_init(&reply, rdata, sizeof(rdata), 4);
bio_init_from_txn(&msg, txn);
res = func(bs, txn, &msg, &reply);//这里解析了驱动发送过来数据,调用func即svcmgr_handler
if (txn->flags & TF_ONE_WAY) {
binder_free_buffer(bs, txn->data.ptr.buffer);
} else {
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
}
}
ptr += sizeof(*txn);
break;
}
..省略
default:
ALOGE("parse: OOPS %d\\n", cmd);
return -1;
}
}
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;
..省略
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
if ((len != (sizeof(svcmgr_id) / 2)) ||
memcmp(svcmgr_id, s, sizeof(svcmgr_id))) {
fprintf(stderr,"invalid id %s\\n", str8(s, len));
return -1;
}
..省略
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
s = bio_get_string16(msg, &len);
if (s == NULL) {
return -1;
}
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:
s = bio_get_string16(msg, &len);
..省略
handle = bio_get_ref(msg);//获取handle即binder实体对象的引用
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
..省略
}
bio_put_uint32(reply, 0);
return 0;
}
先看看serciinfo这个结构体:
struct svcinfo
{
struct svcinfo *next;
uint32_t handle;//最关键的一个binder服务对象的一个handle,系统唯一,servicemanager自己的默认是0
struct binder_death death;
int allow_isolated;
size_t len;
uint16_t name[0];//服务名字非常关键,方便加入和获取服务
};
有一句关键 handle = bio_get_ref(msg);这里就是获取handle即binder实体对象的引用
uint32_t bio_get_ref(struct binder_io *bio)
{
struct flat_binder_object *obj;
..省略
if (obj->type == BINDER_TYPE_HANDLE) //这里传递的flat_binder_object都应该要是handle类型的
return obj->handle;
return 0;
}
这里在看主要的do_add_service:
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)
{
struct svcinfo *si;
..省略
si = find_svc(s, len);//寻找是否已经有了
if (si) {
//已经注册添加就不用再次加了到链表
} else {//没有添加过,就需要构造对象进行添加到
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));//构造除svcinfoj结构体
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;
}
..省略
return 0;
}
其实添加addService主要就是在servicemanager进程中构造除一个svcinfoj,放入链表,那其实这里我们可以猜猜获取是不是肯定从这个链表中根据service的名字查询svcinfo,然后返回handle过程
来看看do_find_service:
uint32_t do_find_service(const uint16_t *s, size_t len, uid_t uid, pid_t spid)
{
struct svcinfo *si = find_svc(s, len);//根据名字来查询链表
if (!si || !si->handle) {
return 0;
}
..省略
return si->handle;//返回结构的handle
}
总结:
ServiceManager为什么叫做binder通信过程的dns服务器呢?相信看完源码大家就非常清楚,它其实干的事情主要就是2个:
1、添加系统中新的binder服务,包装成了一个本地结构体svcinfo,它的最重要参数就是handle,返回了handle才可以在binder驱动中寻找到真正的binder服务实体对象
2、根据传递过来的service名字查询但其servicemanager是否已经注册了该服务,如果注册则返回该服务对应handle
以上是关于Android Framework实战课程-binder专题之ServiceManager启动及运行篇的主要内容,如果未能解决你的问题,请参考以下文章
Android Framework实战课程-binder专题之ServiceManager启动及运行篇
Android Framework实战课程-binder专题之ServiceManager启动及运行篇
千里马Android Framework实战课程-应用程序app的Binder启动篇
千里马Android Framework实战课程-应用程序app的Binder启动篇