有了《ServiceManager如何响应checkService请求》的探索,研究addService就轻车熟路了,中间过程不再多说,仅把关键节点列出:

frameworks/native/cmds/servicemanager/service_manager.c:347

int main(int argc, char **argv)
{
……
binder_loop(bs, svcmgr_handler);
……
}

frameworks/native/cmds/servicemanager/binder.c:372

void binder_loop(struct binder_state *bs, binder_handler func)
{
……
for (;;) {
……
res = binder_parse(bs, , (uintptr_t) readbuf, bwr.read_consumed, func);
……
}
}

frameworks/native/cmds/servicemanager/binder.c:204

int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
……
case BR_TRANSACTION: {
struct binder_transaction_data *txn = (struct binder_transaction_data *) ptr;
……
if (func) {
unsigned rdata[/];
struct binder_io msg;
struct binder_io reply;
int res; bio_init(&reply, rdata, sizeof(rdata), );
bio_init_from_txn(&msg, txn);
res = func(bs, txn, &msg, &reply);
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
}
ptr += sizeof(*txn);
break;
}
…… return r;
}

此时的内存数据结构为:

frameworks/native/cmds/servicemanager/service_manager.c:244

int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply)
{
struct svcinfo *si;
uint16_t *s;
size_t len;
uint32_t handle;
uint32_t strict_policy;
int allow_isolated; …… switch(txn->code) {
…… case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len); // "service.testservice"
if (s == NULL) {
return -;
}
handle = bio_get_ref(msg);
allow_isolated = bio_get_uint32(msg) ? : ; // 0
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -;
break; ……
default:
ALOGE("unknown code %d\n", txn->code);
return -;
} bio_put_uint32(reply, );
return ;
}

SVC_MGR_ADD_SERVICE分之内从msg读出的数据对照“服务端为addService组织的请求数据”示意图很容易拆解出来,需要看一下bio_get_ref(…),frameworks/native/cmds/servicemanager/binder.c:627

uint32_t bio_get_ref(struct binder_io *bio)
{
struct flat_binder_object *obj; obj = _bio_get_obj(bio);
if (!obj)
return ; if (obj->type == BINDER_TYPE_HANDLE)
return obj->handle; return ;
}

frameworks/native/cmds/servicemanager/binder.c:611

static struct flat_binder_object *_bio_get_obj(struct binder_io *bio)
{
size_t n;
size_t off = bio->data - bio->data0; /* TODO: be smarter about this? */
for (n = ; n < bio->offs_avail; n++) {
if (bio->offs[n] == off)
return bio_get(bio, sizeof(struct flat_binder_object));
} bio->data_avail = ;
bio->flags |= BIO_F_OVERFLOW;
return NULL;
}

经过前面几条bio_get_xxx,msg的data指针已经挪到了flat_binder_object实体处,如下图所示,橙色箭头表示msg初始化后到执行bio_get_ref(msg)之前,data指针的挪动情况。_bio_get_obj(…)负责将此flat_binder_object实体返回。

frameworks/native/cmds/servicemanager/service_manager.c:194

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)
{ // s="service.testservice", allow_isolated=0, handle=?
struct svcinfo *si; …… si = find_svc(s, len);
if (si) {
if (si->handle) {
ALOGE("add_service('%s',%x) uid=%d - ALREADY REGISTERED, OVERRIDE\n",
str8(s, len), handle, uid);
svcinfo_death(bs, si);
}
si->handle = handle;
} else {
// 重点在这里,如果服务没有add过,则为之创建节点,保存名字和handle
si = malloc(sizeof(*si) + (len + ) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -;
}
si->handle = handle;
si->len = len;
memcpy(si->name, s, (len + ) * 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;
} binder_acquire(bs, handle);
binder_link_to_death(bs, handle, &si->death);
return ;
}

到这就结束了,最终的落地代码出乎意料的简单:它只是保存服务的name和binder,并把它们串到链表上去。等待客户端checkService则返回handle。总感觉谜团还是没解决,这个handle也就是服务端组织的flat_binder_object数据究竟怎么做到的连接客户端与服务端?ServiceManager的角色应该让C/S关联起来,接下来C、S之间就可以直接通过binder通信了,可是flat_binder_object里面只是保存了服务端的几个指针,客户端怎么凭着这坨binder数据链接到服务端的呢?看来还得研究一条具体的服务请求及响应才能找到最终的答案。

Binder学习笔记(七)—— ServiceManager如何响应addService请求的更多相关文章

  1. Binder学习笔记(九)—— 服务端如何响应Test()请求 ?

    从服务端代码出发,TestServer.cpp int main() { sp < ProcessState > proc(ProcessState::self()); sp < I ...

  2. Binder学习笔记(五)—— Parcel是怎么打包数据的?

    前文中曾经遇到过Parcel,从命名上知道他负责数据打包.在checkService的请求/响应体系中,Parcel只打包了基本数据类型,如Int32.String16……后面还要用于打包抽象数据类型 ...

  3. Binder学习笔记(十二)—— binder_transaction(...)都干了什么?

    binder_open(...)都干了什么? 在回答binder_transaction(...)之前,还有一些基础设施要去探究,比如binder_open(...),binder_mmap(...) ...

  4. Binder学习笔记(八)—— 客户端如何组织Test()请求 ?

    还从客户端代码看起TestClient.cpp:14 int main() { sp < IServiceManager > sm = defaultServiceManager(); / ...

  5. Java IO学习笔记七:多路复用从单线程到多线程

    作者:Grey 原文地址:Java IO学习笔记七:多路复用从单线程到多线程 在前面提到的多路复用的服务端代码中, 我们在处理读数据的同时,也处理了写事件: public void readHandl ...

  6. (转)Qt Model/View 学习笔记 (七)——Delegate类

    Qt Model/View 学习笔记 (七) Delegate  类 概念 与MVC模式不同,model/view结构没有用于与用户交互的完全独立的组件.一般来讲, view负责把数据展示 给用户,也 ...

  7. Learning ROS for Robotics Programming Second Edition学习笔记(七) indigo PCL xtion pro live

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS forRobotics Pro ...

  8. Typescript 学习笔记七:泛型

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  9. python3.4学习笔记(七) 学习网站博客推荐

    python3.4学习笔记(七) 学习网站博客推荐 深入 Python 3http://sebug.net/paper/books/dive-into-python3/<深入 Python 3& ...

随机推荐

  1. [IIS] 不能加载类型System.ServiceModel.Activation.HttpModule

    Could not load type ‘System.ServiceModel.Activation.HttpModule’ from assembly ‘System.ServiceModel, ...

  2. LTE230方案示意图

    普天LTE230产品及解决方案   责任编辑:耿鹏飞 2016.12.26 16:42 来源:通信世界网 LTE230 普天   一.LTE230系统特点 (一)系统背景 随着社会的快速发展,能源危机 ...

  3. 2018年长沙理工大学第十三届程序设计竞赛 E小木乃伊到我家(spfa模版)

    链接:https://www.nowcoder.com/acm/contest/96/E来源:牛客网 小木乃伊到我家 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他 ...

  4. Excel开发学习笔记:新建文档级的excel解决方案

    工作中遇到一个数据处理自动化的问题,于是打算开发一个基于excel的小工具.在业余时间一边自学一边实践,最近终于完成了雏形.抽空把一些知识写下来以备今后参考,因为走的是盲人摸象的野路子,幼稚与错误请多 ...

  5. select *和select 全部

    select *和select 全部字段 在查询上效果是一样的,速度也是一样的. 不过理论上来说select *反而会快点. 因为 1.select 全部字段在数据传输上消耗会更多,如果几百个字段这个 ...

  6. 第五章 JVM调优(待续)

    Java虚拟机内存模型 JVM内存分配参数 垃圾收集基础 常用调优案列和方法 实用JVM参数 实战JVM调优

  7. javascript——事件处理模型(DOM 和 IE)

    javascript的事件处理模型分为 DOM事件处理模型和 IE事件处理模型. 一.DOM事件流模型 DOM事件流分为三个阶段:捕获阶段.目标阶段.冒泡阶段. 捕获阶段:自上而下,由document ...

  8. 问题:sqlserver 跨服务器连接;结果:Sql Server 跨服务器连接

    Sql Server 跨服务器连接 用openrowset连接远程SQL或插入数据 --如果只是临时访问,可以直接用openrowset --查询示例 select * from openrowset ...

  9. NSOperation/NSOperationQueue详细使用介绍

      一.简介 (1)是使用GCD实现的一套Objective-C的API (2)是面向对象的线程技术 (3)提供了一些在GCD中不容易实现的特性,如:限制最大并发数量.操作之间的依赖关系   NSOp ...

  10. CSS制作水平垂直居中对齐 多种方式各有千秋

    作为前端攻城师,在制作Web页面时都有碰到CSS制作水平垂直居中,我想大家都有研究过或者写过,特别的其中的垂直居中,更是让人烦恼.这段时间,我收 集了几种不同的方式制作垂直居中方法,但每种方法各有千秋 ...