原文链接:http://www.cnblogs.com/dyllove98/archive/2013/08/01/3231080.html       

在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上下文管理者

int binder_become_context_manager(struct binder_state *bs){return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);}调用驱动程序设置这个进程为管理者BINDER_SET_CONTEXT_MGR

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驱动程序。

更多相关文章

  1. 解决Android(安卓)sdk manager无法访问google服务器更新的问题
  2. Android(安卓)默认AP名字,以及AP名字存储路径
  3. Android(安卓)VOIP拨打电话机制分析
  4. Android中调用Paint的measureText()方法取得字符串显示的宽度值
  5. 解决Android中Fragment调用startactivityforresult不能返回结果
  6. ActivityManagerService源码分析(一)
  7. Android结合ButterKnife创建自己的BaseActivity
  8. android UI结构 (1)Activity 与 Window
  9. Android目录结构--drawable和drawable-v24区别

随机推荐

  1. Android的Graphic System
  2. eclispe中Android AVD出现"No system ima
  3. Android跨进程启动Service流程及常见问题
  4. adb 超快速截图bash脚本
  5. Android 注册广播有几种方式及优缺点
  6. Android(安卓)ListView记录上次滑动时位
  7. 在android中运行java main方法
  8. Android中获取系统通讯录联系人并解决And
  9. android studio 添加按钮点击事件的三种
  10. Android NDK学习笔记15-配置AndroidStudi