本文主要讲述binder机制中重要的管理员角色ServiceManager学习理解(本文源码参考Android N 7.1.1 )
由上图看出,ServiceManager是Service的管理员,作用十分重要:
1.对于Service来说,系统所有的服务都需要向ServiceManager注册;
2.对于Client来说,所有Client需要使用系统服务时,必须向ServiceManager申请获取相应的服务端代理。
我们从源码分析Native 层 ServiceManager的启动流程和服务流程。
init.rc中将触发early-boot和boot阶段。
system/core/rootdir/init.rc
on late-init
trigger early-boot
trigger boot
在boot阶段的最后,进行class_start core的操作
on boot
.......
class_start core
在system/core/init/builtins.cpp中,class_start对应的处理函数是do_class_start:
static int do_class_start(const std::vector<std::string>& args) {
//此时,args为“core”
ServiceManager::GetInstance().
ForEachServiceInClass(args[1], [] (Service* s) { s->StartIfNotDisabled(); });
return 0;
}
将对service对象中class字段等于“core”的所有服务,执行StartIfNotDisabled操作。
bool Service::StartIfNotDisabled() {
if (!(flags_ & SVC_DISABLED)) {
//启动服务
return Start();
} else {
flags_ |= SVC_DISABLED_START;
}
return true;
}
bool Service::Start() {
//参数检查等操作
..........
pid_t pid = fork();
if (pid == 0) {
//fork出子进程后,为子进程设置参数
......
//启动对应的main函数
if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) {
..............
}
}
......
}
执行service_manager.c的main函数则ServiceManager便启动起来,值得注意的是,ServiceManager是独立的进程,是init进程的子进程。而Zygote进程的class字段为main,启动顺序在servicemanager之后。
Native层的service_manager的main函数在frameworks/native/cmds/servicemanager/service_manager.c中定义,接着上面,我们来看看service_manager.c启动的时候main函数都做了什么:
frameworks/native/cmds/servicemanager/service_manager.c
int main()
{
struct binder_state *bs;
union selinux_callback cb;
//1.打开binder驱动,在内存映射128k
bs = binder_open(128*1024);
...
//2.设置自己为service manager
if (binder_become_context_manager(bs)) {
...
}
//3.selinux相关操作
...
//4.进入循环处理请求
binder_loop(bs, svcmgr_handler);
}
frameworks/native/cmds/servicemanager/binder.c
struct binder_state *binder_open(size_t mapsize)
{
//创建binder_state结构体并分配内存
struct binder_state *bs;
struct binder_version vers;
bs = malloc(sizeof(*bs));
if (!bs) {
errno = ENOMEM;
return NULL;
}
//打开binder设备,应该就是一个文件
bs->fd = open("/dev/binder", O_RDWR | O_CLOEXEC);
...
//判断内核版本和用户空间的版本是否一致
if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
(vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
...
}
//完成内存映射
bs->mapsize = mapsize;
bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
return bs; //返回binderstate结构体给ServiceManager
}
.......................................................
//binder_state数据结构:
binder.c
struct binder_state
{
int fd; //binder文件句柄,binder设备文件描述符
void *mapped;//把设备文件/dev/binder映射到进程空间的起始地址
size_t mapsize;//映射的空间大小
};
Android里,每个service注册时,binder都会给它关联一个handle值,客户端可以根据服务的handle值向ServiceManager请求对应的服务代理,负责这个管理任务的就是ServiceManager。ServiceManager将自己的handle值设置为0,于是其它的进程与其通信时,不需要进行额外的查询
int binder_become_context_manager(struct binder_state *bs)
{
//将ServiceManager对应的binder句柄handle设置为0
return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
binder.c
void binder_loop(struct binder_state *bs, binder_handler func)
{
//告诉binder驱动,servicemanager准备进入循环
readbuf[0] = BC_ENTER_LOOPER;
binder_write(bs, readbuf, sizeof(uint32_t));
//进入循环处理
for (;;) {
bwr.read_size = sizeof(readbuf);
bwr.read_consumed = 0;
bwr.read_buffer = (uintptr_t) readbuf;
// 向binder驱动去查询是否有向自己发的请求
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
...
// 当收到数据后,利用binder_parse解析数据,然后调用func处理,此处func为svcmgr_handler
res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
...
}
}
看到service_manager.c的初始化main函数主要做了如下操作:
下面来看下binder_looper中是如何使用binder_parse()处理请求的:
int binder_parse(struct binder_state *bs, struct binder_io *bio,
uintptr_t ptr, size_t size, binder_handler func)
{
int r = 1;
uintptr_t end = ptr + (uintptr_t) size;
while (ptr < end) {
uint32_t cmd = *(uint32_t *) ptr;
ptr += sizeof(uint32_t);
switch(cmd) {
case BR_NOOP: break;
case BR_TRANSACTION_COMPLETE: break;
case BR_INCREFS:
case BR_ACQUIRE:
case BR_RELEASE:
case BR_DECREFS:
ptr += sizeof(struct binder_ptr_cookie);
break;
case BR_TRANSACTION: { //service onTransaction
struct binder_transaction_data *txn = (struct binder_transaction_data *) 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);
//调用service_manager.c中的svcmgr_handler去处理数据
res = func(bs, txn, &msg, &reply);
if (txn->flags & TF_ONE_WAY) {
binder_free_buffer(bs, txn->data.ptr.buffer);
} else {
//将Service_manager对客户端的回应数据(reply)返回给Binder驱动
binder_send_reply(bs, &reply, txn->data.ptr.buffer, res);
}
}
ptr += sizeof(*txn);
break;
}
case BR_REPLY:
case BR_DEAD_BINDER:
//如果与serviceManager通信的binder死亡,需要调用对应的处理函数
death->func(bs, death->ptr);
case BR_FAILED_REPLY:
case BR_DEAD_REPLY:
default:
ALOGE("parse: OOPS %d\n", cmd);
return -1;
}
}
return r;
}
binder_loop(bs, svcmgr_handler); 中使用svcmgr_handler去处理servicemanager从binder驱动中拿到的请求,然后把返回值作为回应通过binder_send_reply()函数返回给客户端。
int svcmgr_handler(struct binder_state *bs,
struct binder_transaction_data *txn,
struct binder_io *msg,
struct binder_io *reply) {
//进行参数有效性检查等操作
.............
//根据收到数据中携带的code字段,执行相应的操作
switch(txn->code) {
case SVC_MGR_GET_SERVICE:
case SVC_MGR_CHECK_SERVICE:
//从收到数据中读出需查找服务的名称,得到一个Service
s = bio_get_string16(msg, &len);
.......
//得到服务对应的句柄
//根据名称进行匹配,在返回信息前会进行权限检查
handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid);//查找服务的handle
......
//将查找服务的handle信息写入reply
bio_put_ref(reply, handle);
return 0;
case SVC_MGR_ADD_SERVICE:
s = bio_get_string16(msg, &len);
.......
handle = bio_get_ref(msg);//获取handle
allow_isolated = bio_get_uint32(msg) ? 1 : 0;
//向servicemanager注册服务,添加一个服务
//在注册前会进行权限检查,然后利用参数中的信息,构建出服务对象,加入到全局变量svclist中
//同时会调用binder_link_to_death监听新加入服务进程是否死亡
if (do_add_service(bs, s, len, handle, txn->sender_euid,
allow_isolated, txn->sender_pid))
return -1;
break;
case SVC_MGR_LIST_SERVICES: {
//从收到的数据中,取出需要服务的编号
uint32_t n = bio_get_uint32(msg);
//权限检查
if (!svc_can_list(txn->sender_pid, txn->sender_euid)) {
//log
......
return -1;
}
//svclist中记录了注册到servicemanager的服务的信息
si = svclist;
while ((n-- > 0) && si)
si = si->next;
if (si) {
//得到当前注册到servicemanager的服务中,第n个服务的名称
bio_put_string16(reply, si->name);
return 0;
}
return -1;
}
.............
}
从svcmgr_handler的case分支我们可以看出,作为Service_manager主要完成三个功能:
1、得到一个Service;
2、添加一个Service;
3、列出所有的Service;
frameworks/native/cmds/servicemanager/service_manager.c
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;
}
//检查是否有权限获取该服务
if (!si->allow_isolated) {
// If this service doesn't allow access from isolated processes,
// then check the uid to see if it is isolated.
uid_t appid = uid % AID_USER;
if (appid >= AID_ISOLATED_START && appid <= AID_ISOLATED_END) {
return 0;
}
}
//继续跟下去可以看到是selinux权限检测
if (!svc_can_find(s, len, spid, uid)) {
return 0;
}
//返回该name的service的handle值
return si->handle;
}
struct svcinfo *find_svc(const uint16_t *s16, size_t len)
{
struct svcinfo *si;
for (si = svclist; si; si = si->next) { //在svclist中寻找s对应的svcinfo,并返回该service name的svcinfo
if ((len == si->len) &&
!memcmp(s16, si->name, len * sizeof(uint16_t))) {
return si;
}
}
return NULL;
}
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;
//看spid,uid是否有权限进行添加service的操作,跟下看有selinux相关的权限检查
if (!svc_can_register(s, len, spid, uid)) {
return -1;
}
//检查该服务是否已经注册
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 {
si = malloc(sizeof(*si) + (len + 1) * sizeof(uint16_t));
if (!si) {
ALOGE("add_service('%s',%x) uid=%d - OUT OF MEMORY\n",
str8(s, len), handle, uid);
return -1;
}
si->handle = 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;//将该服务添加址svclist中,及完成service的注册
}
binder_acquire(bs, handle);
binder_link_to_death(bs, handle, &si->death);
return 0;
}
list Service的请求只需要把svclist返回给Client即可;由上我们知道所有注册的service信息都在全局list变量中svclist;
至此ServiceManager就完成了解析数据的过程
在3.1中的三个请求处理过程中,特别是get和list Service的请求,最终都需要给客户端相应回应的,我们看到在这两个请求的处理最后,都将相应的回应数据放入了reply的指针中,当从svcmgr_handler()返回后,就把数据带到了binder_parse()中,我们再来回顾一下这里的代码:
int binder_parse(struct binder_state *bs,struct binder_io *bio,uint32_t *ptr,uint32_t size,binder_handler func){
while (ptr < end) {
switch(cmd) {
case BR_TRANSACTION: {
struct binder_txn *txn = (void *) ptr;
binder_dump_txn(txn);
if (func) {
//reply就是svcmgr_handler()中得到的回应
res = func(bs, txn, &msg, &reply);
//将回应数据(reply)返回给Binder驱动
binder_send_reply(bs, &reply, txn->data, res);
}
ptr += sizeof(*txn) / sizeof(uint32_t);
break;
}
}
}
return r;
}
在binder_parse()中又调用binder_send_reply()函数完成回应的操作:
void binder_send_reply(struct binder_state *bs,
struct binder_io *reply,
binder_uintptr_t buffer_to_free,
int status)
{
struct {
uint32_t cmd_free;
binder_uintptr_t buffer;
uint32_t cmd_reply;
struct binder_transaction_data txn;
} __attribute__((packed)) data;
data.cmd_free = BC_FREE_BUFFER;
data.buffer = buffer_to_free;
data.cmd_reply = BC_REPLY;
data.txn.target.ptr = 0;
data.txn.cookie = 0;
data.txn.code = 0;
if (status) {
data.txn.flags = TF_STATUS_CODE;
data.txn.data_size = sizeof(int);
data.txn.offsets_size = 0;
data.txn.data.ptr.buffer = (uintptr_t)&status;
data.txn.data.ptr.offsets = 0;
} else {
data.txn.flags = 0;
data.txn.data_size = reply->data - reply->data0;
data.txn.offsets_size = ((char*) reply->offs) - ((char*) reply->offs0);
data.txn.data.ptr.buffer = (uintptr_t)reply->data0;
data.txn.data.ptr.offsets = (uintptr_t)reply->offs0;
}
//向binder驱动写回应数据
binder_write(bs, &data, sizeof(data));
}
在给Binder发送返回值时,构建了data的数据,并把reply放入其中,并标记了数据的大小,最后通过binder_write()函数将数据写到Binder中,而且写的方法仍然是调用ioctl()。
binder.c
int binder_write(struct binder_state *bs, void *data, size_t len)
{
struct binder_write_read bwr;
int res;
bwr.write_size = len;
bwr.write_consumed = 0;
bwr.write_buffer = (uintptr_t) data;
bwr.read_size = 0;
bwr.read_consumed = 0;
bwr.read_buffer = 0;
//使用ioctl方式将会有的数据写到该service的binder驱动中
res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
return res;
}
在frameworks/base/core/java/android/os/ServiceManager.java定义了java层的ServiceManager
我们看到这里定义的函数有:
private static IServiceManager getIServiceManager() ;//获取ServiceManager实例
public static IBinder getService(String name) ;//获取服务端的binder,即服务端代理
public static void addService(String name, IBinder service) ;//添加服务
public static void addService(String name, IBinder service, boolean allowIsolated) {
public static IBinder checkService(String name) ;
public static String[] listServices() {
...
java层service的管理同样需要经过java层的serviceManager,我们看看几个例子:
AMS启动时
frameworks/base/services/core/java/com/android/server/am/ActivityManagerService.java
public void setSystemProcess() {
try {
ServiceManager.addService(Context.ACTIVITY_SERVICE, this, true);
...
}
PMS启动时
frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public static PackageManagerService main(Context context, Installer installer,
boolean factoryTest, boolean onlyCore) {
PackageManagerService m = new PackageManagerService(context, installer,
factoryTest, onlyCore);
ServiceManager.addService("package", m);
return m;
}
获取Service的binder对象:
如ClipboardService的获取
frameworks/base/core/java/android/content/ClipboardManager.java
static private IClipboard getService() {
synchronized (sStaticLock) {
if (sService != null) {
return sService;
}
IBinder b = ServiceManager.getService("clipboard");
sService = IClipboard.Stub.asInterface(b);
return sService;
}
}
事实上Java层的ServiceManager是Native层ServiceManager的一个Client,而对于Java层其他Service来说,Java层的ServiceManager又是一个Service,负责把其他Client的请求转发给Native层的ServiceManager去处理。Java层的服务注册查询同样也要经过java层的ServiceManager,继而通过JNI方式通过native层的ServiceManager,具体实现方式将在日后的Binder的Java层进行详细的学习阐述。
先简单用图表示: