Android中關於Binder機制的一些感悟

前言

最近重溫了Binder機制,在此把看到的一些心得,寫一寫。

正文

在這裏需要先說明的一點是Client端和Server端以及後面提到的ServiceManager都處於用戶空間、Binder驅動處於內核空間。

Binder是進程間通訊的一種方式。進程間的通訊方式有很多,比如Socket、管道。而Socket、管道這些需要數據的兩次拷貝(Client把數據從自己的進程空間拷貝到內核空間,然後再從內核空間拷貝到Server端的進程空間,這樣Server就能客戶端傳遞的數據,這個過程經歷過了兩次數據拷貝)。而Binder方式只需要一次數據拷貝:只需要Client把數據拷貝到內核空間,然後將拷貝到內核空間的數據同時映射到Server進程虛擬地址空間和內核虛擬地址空間,這樣經過一次數據拷貝,客戶端和服務端就能進行通訊了。

注意:並不是所有的Binder服務都會註冊到ServiceManager中的,像AMS、WMS、PMS這些系統的Binder服務是會註冊到SM中並受SM管理的,而像bindService方式創建的Binder服務不會註冊到ServiceManager中,這些註冊到SM中的Binder服務稱爲實名Binder,不需要註冊到ServiceManager中的Binder服務稱之爲匿名Binder,匿名Binder的傳遞和使用需要依賴於實名Binder。

借用網上某位大佬一張圖,如圖所示:

Android啓動的時候會啓動SystemServer進程,SystemServer進程的入口是裏面的main方法:

public static void main(String[] args) {
        new SystemServer().run();
}

這裏又調用了SystemServer裏面的run方法:

private void run() {
       ...

        // Start services.
        try {
            traceBeginAndSlog("StartServices");
            startBootstrapServices();
            startCoreServices();
            startOtherServices();
            SystemServerInitThreadPool.shutdown();
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            traceEnd();
        }
        ...
    }

我們看這裏面的startBootstrapServices()方法:

private void startBootstrapServices() {
        ....
        // Activity manager runs the show.
        traceBeginAndSlog("StartActivityManager");
        mActivityManagerService = mSystemServiceManager.startService(
                ActivityManagerService.Lifecycle.class).getService();
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
        mActivityManagerService.setInstaller(installer);
        traceEnd();

        ...

        traceBeginAndSlog("SetSystemProcess");
        mActivityManagerService.setSystemProcess();
        traceEnd();

        ...
    }

在這裏,我們看到創建了ActivityManagerService對象,並通過下面的mActivityManagerService.setSystemProcess();啓動了這個ActivityManagerService。

看下ActivityManagerService中的setSystemProcess()這個方法:

public void setSystemProcess() {
        ...

            ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                    DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
        ...
}

在這裏也就是執行了ServiceManager把創建的這個ActivityManagerService對象加入了ServiceManager中創建的映射表裏。

Context.ACTIVITY_SERVICE其實就是“activity”字符串。到時候我們可以通過getService(Context.ACTIVITY_SERVICE),通過這個獲取到存儲在映射表裏面的ActivityManagerService變量。例如:

ActivityManager activityManager = (android.app.ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);

ActivityManager就是一個殼,它的存在避免了AMS直接暴露給應用程序,而是通過對外提供的ActivityManager來操作AMS,這樣更安全,下面我們看一下ActivityManger裏面的getService方法:

public static IActivityManager getService() {
        return IActivityManagerSingleton.get();
    }

看到這裏面調用了IActivityManagerSingleton的get方法,看一下IActivityManagerSingleton:

 private static final Singleton<IActivityManager> IActivityManagerSingleton =
            new Singleton<IActivityManager>() {
                @Override
                protected IActivityManager create() {
                    final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;
                }
            };

首先看下Singleton類的定義:

package android.util;

/**
 * Singleton helper class for lazily initialization.
 *
 * Modeled after frameworks/base/include/utils/Singleton.h
 *
 * @hide
 */
public abstract class Singleton<T> {
    private T mInstance;

    protected abstract T create();

    public final T get() {
        synchronized (this) {
            if (mInstance == null) {
                mInstance = create();
            }
            return mInstance;
        }
    }
}

其中get是final的方法,不可以覆蓋,create是可以覆蓋的。

主要看這裏的兩行代碼:

final IBinder b = ServiceManager.getService(Context.ACTIVITY_SERVICE);
                    final IActivityManager am = IActivityManager.Stub.asInterface(b);
                    return am;

 

這個地方是使用了AIDL的方式(Android7.0及之前,AMS通過代理模式來完成Binder通信,8.0之後,AMS通過AIDL完成Binder通信。),通過調用ServiceManager的getService方法查詢出AMS的信息並轉換爲代理對象am。這個am對象是IActivityManager類型的,而IActivityManager是個aidl,根據aidl的規則和原理,可以知道遠程服務的具體實現一定是IActivityManager.Stub的實現類,而AMS實現了IActivityManager.Stub,所以AMS是遠程服務的具體實現。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章