Android binder (4): Service Manager的初始化
来源:互联网 发布:java返回值前面加泛型 编辑:程序博客网 时间:2024/06/05 12:40
其实init进程启动后,ServiceManager进程的启动,远比zygote要早,因为在启动zygote进程时需要用到ServiceManager进程的服务。ServiceManager是一个守护进程,它维护着系统服务和客户端的binder通信。
在Android系统中用到最多的通信机制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驱动程序组成。其中Client、Service和ServiceManager运行在用户空间,而Binder驱动程序运行在内核空间。核心组件就是 Binder驱动程序了,而ServiceManager提供辅助管理的功能,无论是Client还是Service进行通信前首先要和ServiceManager取得联系。而ServiceManager是一个守护进程,负责管理Server并向Client提供查询Server的功能。
service servicemanager /system/bin/servicemanager class core user system group system critical onrestart restart healthd onrestart restart zygote onrestart restart media onrestart restart surfaceflinger onrestart restart drm
./frameworks/native/cmds/servicemanager/service_manager.c
int main(int argc, char **argv){ struct binder_state *bs; bs = binder_open(128*1024); //打开/dev/binder设备,并且做内存映射(binder的精华所在) if (!bs) { ALOGE("failed to open binder driver\n"); return -1; } //让自己(service manager )成为binder的“大管家" if (binder_become_context_manager(bs)) { ALOGE("cannot become context manager (%s)\n", strerror(errno)); return -1; } svcmgr_handle = BINDER_SERVICE_MANAGER; binder_loop(bs, svcmgr_handler); //进入循环,等待处理事件。 return 0;}
./frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(size_t mapsize){ struct binder_state *bs; struct binder_version vers; bs = malloc(sizeof(*bs)); if (!bs) { errno = ENOMEM; return NULL; } bs->fd = open("/dev/binder", O_RDWR); if (bs->fd < 0) { fprintf(stderr,"binder: cannot open device (%s)\n", strerror(errno)); goto fail_open; } if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) || (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) { fprintf(stderr, "binder: driver version differs from user space\n"); 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; } return bs;fail_map: close(bs->fd);fail_open: free(bs); return NULL;}
总结
守护进程servicemanager循环从binder设备文件读取数据,然后解析并响应请求,包括服务端的添加服务请求和客户端的查询,获取服务的请求。
=======================
参考另外一个网友写的:
Android 开发之serviceManager分析
在Android系统中用到最多的通信机制就是Binder,Binder主要由Client、Server、ServiceManager和Binder驱动程序组成。其中Client、Service和ServiceManager运行在用户空间,而Binder驱动程序运行在内核空间。核心组件就是Binder驱动程序了,而ServiceManager提供辅助管理的功能,无论是Client还是Service进行通信前首先要和ServiceManager取得联系。而ServiceManager是一个守护进程,负责管理Server并向Client提供查询Server的功能。
在init.rc中servicemanager是作为服务启动的,而且是在zygote启动之前service servicemanager /system/bin/servicemanagerclass coreuser systemgroup systemcriticalonrestart restart zygoteonrestart restart mediaonrestart restart surfaceflingeronrestart restart drm
源码位置:frameworks/base/cmds/servicemanager/service_manager.c
int main(int argc, char** argv){struct binder_state *bs;void* svcmgr = BINDER_SERVICE_MANAGER;bs = binder_open(128*1024);binder_become_context_manager(bs);svcmgr_handle = svcmgr;binder_loop(bs, svcmgr_handler);return 0;}
这里main函数主要有三个功能:
1)打开Binder设备文件
首先我们来看看这个struct binder_state结构体
struct binder_state
{
int fd; // 文件描述符,打开/dev/binder设备
void* mapped; // 把设备文件/dev/binder映射到进程空间的起始地址
unsigned mapsize; // 映射内存空间的大小
};
宏:#define BINDER_SERVICE_MANAGER ((void*)0)
表示ServiceManager对应的句柄为0,表面自己是服务器管理者。其他的Server进程句柄值都是大于0的。
struct binder_state* binder_open(unsigned mapsize){struct binder_state* bs;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);return bs;}这里主要就是打开Binder设备,映射128K的内存地址空间
2)告诉Binder驱动程序自己是Binder上下文管理者
<span style="margin: 0px; padding: 0px;">int binder_become_context_manager(struct binder_state *bs){return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);}调用驱动程序设置这个进程为管理者BINDER_SET_CONTEXT_MGR</span>
3)进入一个无线循环,充当server角色,等待Client的请求
void binder_loop(struct binder_state bs, binder_handler func){struct binder_write_read bwr;unsigned readbuf[32];bwr.write_size = 0;bwr.write_consumed = 0;bwr.write_buffer = 0;readbuf[0] = BC_ENTER_LOOPER;// 设置事件类型为LOOPER// 调用ioctl函数,通知Binder设备servicemanager开始进入loop状态binder_write(bs, readbuf, sizeof(unsigned));for(;;) {bwr.read_size = sizeof(readbuf);bwr.read_consumed = 0;bwr.read_buffer = (unsigned)readbuf;// 进入Binder设备缓冲区,检查是否有IPC请求ioctl(bs->fd, BINDER_WRITE_READ, &bwr);// 对于请求调用binder_parse进行解析处理binder_parse(bs, 0, readbuf, bwr.read_consumed, func);}}这里我们看下struct binder_write_read这个结构体:struct binder_write_read{signed long write_size;signed long write_consumed;// bytes consumed by driverunsigned long write_buffer;signed long read_size;signed long read_consumed;// bytes consumed by driverunsigned long read_buffer;};int binder_parse(struct binder_state *bs, struct binder_io *bio, uint32_t *ptr, uint32_t size, binder_handler func){uint32_t *end = ptr + (size / 4);while(ptr < end) {uint32_t cmd = *ptr++;switch(cmd) {......case BR_TRANSACTOIN:{// 收到请求进行处理struct bindeer_txn *txn = (void*) ptr;if(func) {unsigned rdata[256/4];struct binder_io msg;struct binder_io reply;bio_init(&reply, rdata, sizeof(rdata), 4);bio_init_from_txn(&msg, txn);ret = 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(bio) {bio_init_from_txn(bio, txn);bio = 0;}else {// to 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;}...}}return r;}/*这里binder_parse函数首先将binder读取过来的请求数据转化为bindeer_txn结构体,然后根据这个结构体初始化binder_io msg,交给回调函数svcmgr_handler处理,同时返回一个binder_io reply,最后将这个reply发送返回给客户端。*/struc binder_io{char* data;// 指向read/write的数据uint32_t *offs;// 偏移数组uint32_t data_avail;// data中有效字节长 uint32_t offs_avail;// 偏移数组中有效字节长char* data0;// data起始地址uint32_t *offs0;// 偏移buffer的起始地址uint32_t flags;uint32_t unused;};最终调用的处理函数还是svcmgr_handler,终于要开始出来请求数据了: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;if(txn->target != svcmgr_handler)return -1;// 首先判断这个消息的是不是发给自己的strict_policy = bio_get_uint32(msg);s = bio_get_string16(msg, &len);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);// 根据服务名字查找链表bio_put_ref(reply, ptr);return 0;case SVC_MGR_ADD_SERVICE: // 添加服务s = bio_get_string16(msg, &len);ptr = bio_get_ref(msg);do_add_service(bs, s, len, ptr, txn->sender_euid);bio_put_uint32(reply, 0);// 告知添加成功return 0;....}return 0;}
首先我们得看看Binder是怎么组织Binder传递消息的数据结构的,根据前面我们知道调用Binder驱动
的时候我们获得了一个void* ptr结构体,强制转化为binder_txn *txn,然后根据这个txn我们获得了
Binder的输入输出结构体binder_io *bio。最后我们不管是处理请求还是发送回复都是处理这个bio结构。
而我们的Binder通信的binder结构是由binder_object来组织的,指向binder_io结构里面data。
首先我们得看看Binder是怎么组织Binder传递消息的数据结构的,根据前面我们知道调用Binder驱动
的时候我们获得了一个void* ptr结构体,强制转化为binder_txn *txn,然后根据这个txn我们获得了
Binder的输入输出结构体binder_io *bio。最后我们不管是处理请求还是发送回复都是处理这个bio结构。
而我们的Binder通信的binder结构是由binder_object来组织的,指向binder_io结构里面data。
struct binder_object{uint32_t type;uint32_t flags;void* pointer;void* cookie;};
上面的binder_object结构体内容依次对应着我们代码中的:
bio_get_uint32(msg);
bio_get_string16(msg, &len);
bio_get_string16(msg, &len);
bio_get_ref(msg);
上面的binder_object结构体内容依次对应着我们代码中的:
bio_get_uint32(msg);
bio_get_string16(msg, &len);
bio_get_string16(msg, &len);
bio_get_ref(msg);
当客户端需要添加服务的时候:SVC_MGR_ADD_SERVICE
1)首先调用bio_get_string16()从binder_io中获得服务名字。
2)调用bio_get_ref()从binder_io中获得服务的binder实体struct binder_object
void* bio_get_ref(struct binder_io* bio){struct binder_object* obj;obj = _bio_get_obj(bio);// 这个函数最终调用的是void* ptr = bio->data;return obj->pointer;}
3)调用do_add_service()将上面的Binder实体引用写到服务中,再通过名字加到全局链表中
int do_add_service(struct binder_state* bs, uint16_t *s, unsigned len, void* ptr, unsigned uid){struct svcinfo *si;svc_can_register(uid, s);// 检查权限si = find_svc(s, len);// 根据名字查找链表,判断是否已经存在si = malloc(sizeof(*si) + (len+1)*sizeof(uin16_t));si->ptr = ptr;//指向上面的binder_object的pointer也就是Binder实体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_acquire(bs, ptr);binder_link_to_death(bs, ptr, &si->death);return 0;}
当客户端需要查询服务的时候:
1)bio_get_string16() 获得服务名字
2)do_find_service() 遍历全局链表svclist,根据服务名字找到对应的服务并返回。
2)bio_put_ref(reply, ptr);这里reply就是需要返回给客户端的结构体,而ptr就是指向目标Binder实体。
void bio_put_ref(struct binder_io* bio, void* ptr){struct binder_object *obj;obj = bio_alloc(bio);obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;obj->type = BINDER_TYPE_HANDLE;obj->pointer = ptr;obj->cookie = 0;}
回到binder_parse函数里面,执行:binder_send_reply()通知Binder驱动程序。
- Android binder (4): Service Manager的初始化
- Android Binder - Service Manager
- Android IPC Binder,Service,Service manager
- Android Binder,Service,Service manager 框架分析
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android系统的Binder机制之一——Service Manager
- Android之Service Manager的Binder守护进程
- service manager和binder service的关系
- android binder机制之二 Service Manager
- Android Framework:Binder(2)-Service Manager
- Android系统Binder机制中的四个组件Client、Server、Service Manager和Binder驱动程序的关系
- 注解框架Android Butter Knife的介绍
- Android 开发60条技术经验总结
- Git:git常用命令
- const
- Android学习笔记 -- 平台框架
- Android binder (4): Service Manager的初始化
- 利用Nginx第三方模块,实现附件打包下载
- 上线 之 上架AppStore10个大坑(下)
- OC字符串的常用方法
- Zookeeper之JAVA API
- 【leetcode】【116】Populating Next Right Pointers in Each Node
- 设计模式之简单工厂模式
- 华为OJ题目(十六):字符串匹配
- Android Studio插件