【转】 Service Manager

标签: service manager | 发表时间:2013-12-06 21:33 | 作者:gdfdfg
出处:http://www.iteye.com

android2.3 ---  Service Manager分析

Android系统Binder机制的总管是Service Manager,所有的Server(System Server)都需要向他注册,应用程序需要向其查询相应的服务。可见其作用是多么的重要,那么我们这里就要重点介绍一下这个。


这里以java层加入ServiceManager及getService为数据流分析一下。

复习一下典型的Binder模式,有利于后面的理解:
1、客户端通过某种方式得到服务器端的代理对象。从客户端角度看来代理对象和他的本地对象没有什么差别。它可以像其他本地对象一样调用其方法,访问其变量。
2、客户端通过调用服务器代理对象的方法向服务器端发送请求。
3、代理对象把用户请求通过Android内核(Linux内核)的Binder驱动发送到服务器进程。 
4、服务器进程处理用户请求,并通过Android内核(Linux内核)的Binder驱动返回处理结果给客户端的服务器代理对象。 
5、客户端收到服务器端的返回结果。


JAVA层代码分析:
ServiceManager.java (frameworks\base\core\java\android\os)

对于xxxManager获取服务端service基本如此用法:
利用ContextImpl.java中的 
public Object getSystemService(String name) 
然后再调用:
ServiceManager.getService(ServiceName);
获取相应的服务端

ex:
@Override
public Object getSystemService(String name) {
if (WIFI_SERVICE.equals(name)) {
  return getWifiManager();
}
-->
private WifiManager getWifiManager()
{
    synchronized (sSync) {
        if (sWifiManager == null) {
            IBinder b = ServiceManager.getService(WIFI_SERVICE);
            IWifiManager service = IWifiManager.Stub.asInterface(b);
            sWifiManager = new WifiManager(service, mMainThread.getHandler());
        }
    }
    return sWifiManager;
}

ok,知道了客户端获取一个Service的方法之后,我们回到ServiceManager的服务端:
private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }


    // Find the service manager
    sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());
    return sServiceManager;
}


BinderInternal.getContextObject() @ BinderInternal.java  是一个native 函数:


android_os_BinderInternal_getContextObject @ android_util_Binder.cpp
返回一个 BinderProxy对象保存到类成员mRemote(ServiceManagerProxy类成员)


public abstract class ServiceManagerNative extends Binder implements IServiceManager
ServiceManagerNative 继承自 Binder 并实现了 IServiceManager 接口,利用 asInterface()则提供一个 ServiceManagerProxy 代理对象使用


class ServiceManagerProxy implements IServiceManager
定义了类ServiceManagerProxy(代理),ServiceManagerProxy继承自IServiceManager,并实现了其声明的操作函数,只会被ServiceManagerNative创建,它实现了IServiceManager的接口,IServiceManager提供了getService和addService两个成员函数来管理系统中的Service。

ok,我们沿着代码继续往前走:

class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    
    public IBinder asBinder() {
        return mRemote;  // 这是一个BinderProxy对象
    }


    public IBinder getService(String name) throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);
        IBinder binder = reply.readStrongBinder();
        reply.recycle();
        data.recycle();
        return binder;
    }
}

上层先利用Parcel对象将数据进行序列化,然后利用transact将数据传给binder驱动,根据 mRemote 是一个 BpBinder 对象继续追踪:

JNI层代码分析:android_util_Binder.cpp 
java 层通过 Binder 对象调用jni函数:
Binder.java: Binder实现的IBinder的接口,他的大部分函数都是通过JNI调用底层实现的BinderProxy是JAVA层的关键类,在JNI通过 gBinderProxyOffsets 来使用

这里只关心它的 onTransact 函数即可

BpBinder 在 BpBinder.h 实现:
class BpBinder : public IBinder
{
    virtual status_t    transact(   uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
}


status_t BpBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    // Once a binder has died, it will never come back to life.
    if (mAlive) {
        status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);
        if (status == DEAD_OBJECT) mAlive = 0;
        return status;
    }

    return DEAD_OBJECT;
}

3、C++ native层实现 service操作实现,其实java层的直接利用jni写入到binder驱动层了:

IServiceManager.cpp (frameworks\base\libs\binder)
class BpServiceManager : public BpInterface<IServiceManager>
{
public:
    // 获取Service服务端
    virtual sp<IBinder> getService(const String16& name) const
    {
        unsigned n;
        for (n = 0; n < 5; n++){
            sp<IBinder> svc = checkService(name);
            if (svc != NULL) return svc;
            LOGI("Waiting for service %s...\n", String8(name).string());
            sleep(1);
        }
        return NULL;
    }


    // 添加Service到ServiceManager管理器
    virtual status_t addService(const String16& name, const sp<IBinder>& service)
    {
        Parcel data, reply;
        data.writeInterfaceToken(IServiceManager::getInterfaceDescriptor());
        data.writeString16(name);
        data.writeStrongBinder(service);
        status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
        return err == NO_ERROR ? reply.readExceptionCode() : err;
    }
}

到了这里:
IMPLEMENT_META_INTERFACE(ServiceManager, "android.os.IServiceManager");

// ----------------------------------------------------------------------

status_t BnServiceManager::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)

一般都以为服务端继承BnServiceManager类实现即可:
ServiceManager.h (frameworks\base\cmds\runtime)
class BServiceManager : public BnServiceManager
其实这里不是的,这是在模拟器上的实现方法,请看其下面的Android.mk文件:
ifeq ($(TARGET_SIMULATOR),true)
... 
include $(BUILD_EXECUTABLE)
endif

那么这里到底是怎么回事呢?JAVA层利用jni也是如此操作的。

这里是通过 IPCThreadState 类直接将binder请求写入到binder驱动(/dev/binder),这里简要说一下简单的流程,后续还会继续深入这个问题:

addService @ IServiceManager.cpp
status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
-->
transact @ IPCThreadState
transact() --> writeTransactionData() 写入到binder驱动,这就是核心所在。。。

现在就进入到最重要的 servicemanager 大总管角色中了
源码路径:frameworks\base\cmds\servicemanager\service_manager.c

servicemanager 是一个进程,在init.rc脚本中开机就启动:
service servicemanager /system/bin/servicemanager
    user system
    critical
    onrestart restart zygote
    onrestart restart media
    
从其main中开始分析:
main @ service_manager.c


int main(int argc, char **argv)
{
    struct binder_state *bs;
    void *svcmgr = BINDER_SERVICE_MANAGER;
    bs = binder_open(128*1024);

    if (binder_become_context_manager(bs)) {
        LOGE("cannot become context manager (%s)\n", strerror(errno));
        return -1;
    }

    svcmgr_handle = svcmgr;
    binder_loop(bs, svcmgr_handler);
    return 0;
}

调用binder_open打开binder设备(/dev/binder),其次它调用了binder_become_context_manager函数,这个函数使他自己变为了"Server大总管"

int binder_become_context_manager(struct binder_state *bs)
{
    return ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
}
即成为一个0号句柄,所有的进程都可以通过id=0来访问它。

Service Manager作为一个Server大总管,本身也是一个server。既然是一个server就要时刻准备为客户端提供服务。最好Service Manager调用binder_loop进入到循环状态,并提供了一个回调函数,等待用户的请求。注意他的Service Manager的客户端既包括应用程序(查询和获取服务),也包括Server(注册服务)。

只要server向binder设备写入请求注册Service时,Service Manager的服务处理回调函数将会被调用
这里的回调函数就是 svcmgr_handler:
int svcmgr_handler(struct binder_state *bs,
                   struct binder_txn *txn,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
    // 获取请求数据
    strict_policy = bio_get_uint32(msg);
    s = bio_get_string16(msg, &len);


    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:  // 获取service服务
    case SVC_MGR_CHECK_SERVICE:
        s = bio_get_string16(msg, &len);
        ptr = do_find_service(bs, s, len);
        if (!ptr)
            break;
        bio_put_ref(reply, ptr);
        return 0;


    case SVC_MGR_ADD_SERVICE: // 注册service服务
        s = bio_get_string16(msg, &len);
        ptr = bio_get_ref(msg);
        if (do_add_service(bs, s, len, ptr, txn->sender_euid))
            return -1;
        break;


    case SVC_MGR_LIST_SERVICES: { // 列举service服务
        unsigned n = bio_get_uint32(msg);


        si = svclist;
        while ((n-- > 0) && si)
            si = si->next;
        if (si) {
            bio_put_string16(reply, si->name);
            return 0;
        }
        return -1;
    }
}

这里也是对请求的服务回写到binder驱动,别忘记了客户端同步处理:
transact @ IPCThreadState.cpp
    if ((flags & TF_ONE_WAY) == 0) {
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
    } else {
        err = waitForResponse(NULL, NULL);
    }
--> 这里利用talkWithDriver()利用:
ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) 请求与回应数据。

IPCThreadState 是一个非常关键的类,由其直接于binder驱动打交道,后文将会重点分析。

 

模块层次基本如下:

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [service manager] 推荐:

【转】 Service Manager

- - 移动开发 - ITeye博客
android2.3 ---  Service Manager分析. Android系统Binder机制的总管是Service Manager,所有的Server(System Server)都需要向他注册,应用程序需要向其查询相应的服务. 可见其作用是多么的重要,那么我们这里就要重点介绍一下这个.

Web Service入门

- - 博客 - 伯乐在线
本文来自文章作者 @Jeremy黄国华 的投稿. 伯乐在线也欢迎其他朋友投稿,投稿时记得留下您的新浪微博账号哦~. 目前对Web Service没有统一的定义,定义一:Web Service是自包含的、模块化的应用程序,它可以在Web中被描述、发布、查找以及调用. 定义二:Web Service是基于网络的、分布式的模块化组件,它执行特定的任务,遵守具体的技术规范,这些规范使得Web Service能与其他兼任的组件进行操作.

Android Service 详解

- - CSDN博客移动开发推荐文章
一个Service也是一种应用程序组件,它运行在后台以提供某种服务,通常不具有可见的用户界面. 其它的应用程序组件可以启动一个Service,即使在用户切换到另外一个应用程序后,这个Service还是一直会在后台运行. 此外,一个应用程序也可以绑定到一个Service然后使用进程间通信(IPC)方式与Service之间发生交互.

Web Service的研究

- - CSDN博客系统运维推荐文章
SOA和Web Service. 首先明白SOA和Web Service的关系:. * SOA面向服务架构,用于大型分布式系统的一个概念;. * Web Service是实现SOA的方式之一,不是所有的SOA都是基于Web service的;. * 但Webservice确实为最主流的SOA实现方式,有的人甚至把SOA等同于Webservice.

Simple LightDM Manager : 登录背景修改器

- Jerry - Wow! Ubuntu
通告:问答社区重新上线,已经与 WordPress 整合,如果你之前在本 Blog 上注册过的话,就可用该帐号直接登录. 从 Ubuntu 11.10 开始,Ubuntu 采用 LightDM 作为登录管理器. 现在有开发者制作了一款名为 Simple LightDM Manager  的 tweaking 工具,用户可以通过 GUI 界面来简单快速的改变 LightDM 登录窗口的背景图片及 Logo.

Stingray Traffic Manager 9.0 安装教程

- - 傻子-王跸西的blog-WangBiXi.com
ZXTM 是一款很强大的负载均衡软件.主要用于web服务器.强大的规则功能和监控系统都是非常给力的.. 操作系统: Centos 5.4 64bit. cd ZeusTM_90r2_Linux-x86_64 chmod 777 zinstall 修改权限 ./zinstall 执行安装. 安装过程中会提示–软件安装路径,执行的用户组和用户,确认mac地址,添加授权文件名,设置管理员密码..

Android学习之路——7.Service

- - ITeye博客
这两天又学习了Android四大组件之一的Service. (1)Service不是一个单独的Process,除非特别指派了,也不是一个Thread,但也不是运行在Main Thread中. (3)Service的生命周期:. 调用的Context.startService()   oncreate() --> onStartCommand ()--> Service is running --> The service is stopped by its or a client--> onDestroy() --> Service is shut down .

Android Activity与Service通信

- - CSDN博客移动开发推荐文章
一、当Acitivity和Service处于同一个Application和进程时,通过继承Binder类来实现.      当一个Activity绑定到一个Service上时,它负责维护Service实例的引用,允许你对正在运行的Service进行一些方法调用. 比如你后台有一个播放背景音乐的Service,这时就可以用这种方式来进行通信.

Restful 和 Jersey介绍(Web Service )

- - CSDN博客架构设计推荐文章
REST 2000 年由 Roy Fielding 在博士论文中提出,他是 HTTP 规范 1.0 和 1.1 版的首席作者之一. REST 中最重要的概念是资源(resources) ,使用全球 ID(通常使用 URI)标识. 客户端应用程序使用 HTTP 方法(GET/ POST/ PUT/ DELETE )操作资源或资源集.

service层异常的处理

- - Web前端 - ITeye博客
1、在service方法里面如果对异常进行了捕获的话,该事务是不会进行回滚的.        默认spring事务只在发生未被捕获的 runtimeexcetpion时才回滚.   方案1.例如service层处理事务,那么service中的方法中不做异常捕获,或者在catch语句中最后增加throw new RuntimeException()语句,以便让aop捕获异常再去回滚,并且在controller层要继续捕获这个异常并处理.