Android10_原理機制系列_Binder機制

前言

Binder 從java到c++到kernel,涉及的內容不少,很難在一篇文章中說清楚。這篇主要是自我記錄,方便後續查詢並拆分總結的。
由於涉及的的確很是多,不能面面俱到,因此可能一些地方感受比較模糊、沒說明白的。這須要本身去閱讀了解。文章很長,須要耐心。
關於基礎部分,並非都要了解了才行,而是要徹底弄清楚Binder各個層次須要,列出的一些須要多關注的知識點。
另外,該篇文章着重在註冊服務和獲取服務的過程,有詳細的代碼流程(這個有點複雜、佔篇幅很大部分)輔助理解 註冊和獲取服務過程的總體思想把握。html

基礎

不作詳細介紹,只是列出。
如前言所說,基礎部分並不是都要所有了解纔可理解Binder。只是列出的須要多關注的地方。java

進程空間

這裏的進程空間就是進程在內存中的空間。在linux中,有node

  • 進程分爲內核空間和用戶空間。 內核空間存放內核的代碼和數據,用戶空間存放用戶程序的代碼和數據。
  • 每一個進程經過系統調用進入內核空間。 進程經過系統調用進入內核運行,這時被稱爲內核態 。當進程執行程序本身的代碼時,稱爲用戶態
  • 全部進程共享同一個內核空間。
  • 內核空間爲內核保留,一直駐存在內存中。 不容許應用讀寫該區域或者直接調用內核代碼方法。
  • 用戶空間不能直接訪問硬件設備。

Binder跨進程通訊,就是借用了這個。
示意圖:
user_kernel_space
進程瞭解 能夠參考下:淺談進程&線程

linux

IPC基礎

須要清楚:進程是獨立的,一個進程不能直接訪問另外一個進程。android

進程間若是須要交換數據、進行通訊,這個就是IPC(進程間通訊/跨進程通訊)。能夠參考相關文章大體瞭解下:
隨筆分類 - Android_系統_進程線程

c++

內存映射(mmap)

這裏簡單將,就是將用戶空間一段內存地址映射到內核空間,映射關係創建後,任一修改都能反應到另外一方。

git

Parcel

一個容器對象,包含數據和對象引用,支持序列化和跨進程後的反序列化。這裏主要用於binder的跨進程通訊。

api

AIDL

Android Interface definition language,接口定義語言,能夠了解下。

安全

Binder

IPC在Android中不少:如顯然四大組件都須要進行IPC。
Andriod沒有使用Linux中的各類IPC機制(進程間通訊概述),經過基於OpenBinder的定製修改,實現了本身的一套輕量級的IPC機制---Binder。
在Android中,Binder幾乎用於全部核心的跨進程事件中。cookie

相對於Linux中其餘IPC機制,那麼Binder有什麼優勢呢?

優勢

  • Binder只需進行1次數據拷貝。
    共享內存不需數據拷貝但控制複雜;其餘方式通常須要進行兩次數據拷貝;Binder只需1次,經過內存映射機制進行數據傳遞。
  • 穩定性好。
    C/S架構,職責分明。
  • 安全。
    加入了強大的安全機制。

Binder概述

Binder是基於C/S模式。主要有這幾個部分:

角色 做用
Server進程 服務端,提供服務的進程。
Client進程 客戶端,使用服務的進程。上層應用。
ServerManager進程 管理服務。Server須要向它註冊本身提供的服務。Client向它查詢、獲取須要的服務。
Binder驅動 核心部分,Client經過它發送請求到Server,Server經過它返回結果到Client。內核中的驅動設備/dev/binder。

下面詳述中會具體說到。

Binder---IPC

首先,整體上就如上述進程空間描述。Binder經過內核進行跨進程。
具體點,以下圖:
binder_s_c
服務經過binder驅動註冊到ServiceManager,ServiceManager保存了服務的名稱、handle等信息 並加入svclist列表中。客戶端經過binder驅動向ServiceManager進程查詢獲取到對應的服務的handle,而後binder將信息返回給客戶端,客戶端獲取獲得相應的服務Binder。

詳述Binder的流程

詳述Binder的流程 主要是服務註冊、獲取、ServiceManager相關的代碼流程,這段很長,若是不須要看 能夠直接跳到最後一塊:簡單總結。

下面AMS的註冊和獲取爲例說明。Binder過程比較複雜,其中最需注意的是各個層次(java層/c++/kernel) IBinder對象具體是什麼。
Binder源碼,java層和c++層在 framework/下。驅動層在 kernel/下。
Android AOSP沒有kernel源碼,得單獨下載。這裏閱讀的源碼是AndroidQ的,AOSP部分是android-10.0.0_r40;kernel部分是MTK的,主要兩個文件路徑在kernel-4.9/drivers/android/binder.c和kernel-4.9/include/uapi/linux/android/binder.h。
另外,下面的過程不少地方 不少方法都須要詳細研究的。下面儘可能簡化了,即便這樣(也是水平有限),內容也很長。


主要是一個進程如何與另外一個進程通訊。圍繞這 下面主要介紹了幾點:

  • Service是如何註冊的
  • ServerManager的建立,這裏涉及到Service的註冊和獲取。
  • Client是如何獲取服務的

服務註冊

AMS註冊過程概述

服務是Context.ACTIVITY_SERVICE。

下面是畫的一個註冊過程的相對完整的流程(不是類圖。文章是MD的,能夠直接查看文本看到圖片地址,該圖片地址。使用wps畫的 因爲非會員,圖形個數有限制帶了水印。),再結合代碼詳細說明下。
binder_service_register
這是一個理想的狀態流程,好比實際中不少對象從保存好的地方直接獲取不需從新建立。

簡述:
註冊傳入了兩個主要參數(服務名:activity,Binder:this)。經過一系列調用,最終將服務的名稱和Binder等寫入到了數據包Parcel(data)中,最終進入了Binder驅動。Binder驅動爲AMS建立了binder結點binder_node。最後Binder驅動將相關信息給到ServerManager進程,ServiceManager將其封裝加入svclist列表完成註冊。

註冊詳細過程

系統啓動後,這個服務即開始註冊。這個很簡單,注意傳入的服務名是Context.ACTIVITY_SERVICE(即activity),以及this(AMS自己,也是繼承了IBinder的Binder實體)。

SystemServer.java:
private void startBootstrapServices() {
    ......
    mActivityManagerService.setSystemProcess();
    ......
}

ActivityManagerService.java:
public void setSystemProcess() {
    ......
    ServiceManager.addService(Context.ACTIVITY_SERVICE, this, /* allowIsolated= */ true,
                DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PRIORITY_NORMAL | DUMP_FLAG_PROTO);
    ......
}

ServiceManager.java:
@UnsupportedAppUsage
public static void addService(String name, IBinder service, boolean allowIsolated,
                              int dumpPriority) {
    ......
    getIServiceManager().addService(name, service, allowIsolated, dumpPriority);
    ......
}

getIServiceManager().addService(),這裏須要弄清楚的就是getIServiceManager()和addService()兩個方法,下面正式開始註冊流程。

getIServiceManager()

ServiceManager.java:
@UnsupportedAppUsage
private static IServiceManager getIServiceManager() {
    if (sServiceManager != null) {
        return sServiceManager;
    }

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

關鍵的一句,這裏有幾個須要依次弄清楚的。

  1. BinderInternal.getContextObject()
  2. Binder.allowBlocking()
  3. ServiceManagerNative.asInterface()
  4. getIServiceManager().addService():獲取的是IServiceManager,這也是個接口。須要弄清楚getIServiceManager()獲取的sServiceManager實際對象是什麼在來看addService()方法。
    -----回顧點1: getIServiceManager()具體是什麼對象;addService()具體是什麼

詳細來看下這4點:
先看第一點(1/4)

BinderInternal.getContextObject()

BinderInternal.java:
@UnsupportedAppUsage
public static final native IBinder getContextObject();     

frameworks/base/core/jni/android_util_Binder.cpp:
{ "getContextObject", "()Landroid/os/IBinder;", (void*)android_os_BinderInternal_getContextObject },

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)
{
    sp<IBinder> b = ProcessState::self()->getContextObject(NULL);
    return javaObjectForIBinder(env, b);
}

getContextObject()是native修飾的方法,經過jni,進入了C++。
下面主要來看下ProcessState::self()->getContextObject(NULL)和javaObjectForIBinder(env, b)。
-----回顧點2: getContextObject()具體獲取的是什麼

先看下ProcessState::self()
ProcessState.java:
#ifdef __ANDROID_VNDK__
const char* kDefaultDriver = "/dev/vndbinder";
#else
const char* kDefaultDriver = "/dev/binder";
#endif

#define BINDER_VM_SIZE ((1 * 1024 * 1024) - sysconf(_SC_PAGE_SIZE) * 2)

#define DEFAULT_MAX_BINDER_THREADS 15

sp<ProcessState> ProcessState::self()
{
    ......
    gProcess = new ProcessState(kDefaultDriver);
    return gProcess;
}

ProcessState::ProcessState(const char *driver)
    : mDriverName(String8(driver))
    , mDriverFD(open_driver(driver))
    ......
{
    ......
    mVMStart = mmap(nullptr, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);
    ......
}

static int open_driver(const char *driver)
{
    int fd = open(driver, O_RDWR | O_CLOEXEC);
    if (fd >= 0) {
        int vers = 0;
        status_t result = ioctl(fd, BINDER_VERSION, &vers);
    ......
    size_t maxThreads = DEFAULT_MAX_BINDER_THREADS;
    result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);
    ......
}

從代碼可以看到最終經過open_driver()方法打開了/dev/binder或者/dev/vndbinder驅動。經過ioctl進入binder內核並創建聯繫,在binder內核中建立了binder_proc並設置進程的最大線程數。
注意兩個個設置:

  • DEFAULT_MAX_BINDER_THREADS:這個fd最大線程數爲15
  • BINDER_VM_SIZE:ProcessState初始話的內存映射大小:1G-8k(注:這個值也又不一樣的狀況,這裏不擴展)

在接着看ProcessState::self()->getContextObject(NULL)
sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}

sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    ......
    handle_entry* e = lookupHandleLocked(handle);
    if (e != nullptr) {
        IBinder* b = e->binder;
        if (b == nullptr || !e->refs->attemptIncWeak(this)) {
            .......
            b = BpBinder::create(handle);
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }
    return result;
}

回到回顧點2,getContextObject()獲取了句柄爲0的BpBinder。先lookupHandleLocked()嘗試獲取,沒有則建立了一個BpBinder對象。
BpBinder的handle,若是是0 則該BpBinder是servicemanager的binder引用,若是非0 其handle值就是不一樣Service的hanlde 關聯了各個Service。也就是說任何的系統service均可以經過BpBinder(0)就能知道servicemanager的地址。
-----注意點1: 這個handle爲0的BpBinder很重要,binder驅動等地方都有關聯。

在來看return的方法,javaObjectForIBinder(env, b):
frameworks/base/core/jni/android_util_Binder.cpp:  
jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    ......
    if (val->checkSubclass(&gBinderOffsets)) {
        // It's a JavaBBinder created by ibinderForJavaObject. Already has Java object.
        jobject object = static_cast<JavaBBinder*>(val.get())->object();
        LOGDEATH("objectForBinder %p: it's our own %p!\n", val.get(), object);
        return object;
    }

    BinderProxyNativeData* nativeData = new BinderProxyNativeData();
    nativeData->mOrgue = new DeathRecipientList;
    nativeData->mObject = val;
    jobject object = env->CallStaticObjectMethod(gBinderProxyOffsets.mClass,
            gBinderProxyOffsets.mGetInstance, (jlong) nativeData, (jlong) val.get());
    ......
    return object;
}

在註冊過程,返回的是BinderProxy。前面知道傳入的是BpBinder對象,這是native層的對象在Java層沒法使用,轉換成BinderProxy。


接着看第二點(2/4)

Binder.allowBlocking()

Binder.java:
public static IBinder allowBlocking(IBinder binder) {
    try {
        if (binder instanceof BinderProxy) {
            ((BinderProxy) binder).mWarnOnBlocking = false;
        } else if (binder != null && binder.getInterfaceDescriptor() != null
                && binder.queryLocalInterface(binder.getInterfaceDescriptor()) == null) {
            Log.w(TAG, "Unable to allow blocking on interface " + binder);
        }
    } catch (RemoteException ignored) {
    }
    return binder;
}

這個沒什麼好說的。


再看第三點(3/4)

ServiceManagerNative.asInterface()

ServiceManagerNative.java:
@UnsupportedAppUsage
static public IServiceManager asInterface(IBinder obj)
{
    ......
    IServiceManager in =
            (IServiceManager)obj.queryLocalInterface(descriptor);
    if (in != null) {
        return in;
    }
    .......
    return new ServiceManagerProxy(obj);
}

前面傳遞的參數obj是一個保存着BpBinder的BinderProxy對象,這個BpBinder的handle是0(即關聯servicemanager,後續經過transact傳入binder驅動 找到目標進程)。
queryLocalInterface獲取本地binder,此時in返回是null,因此這裏返回了一個ServiceManagerProxy對象,並傳入了BinderProxy對象。後續就經過這個BinderProxy代理對象進行通訊。

回到回顧點1,從上面一系列能夠看出getIServiceManager().addService(name, service, allowIsolated, dumpPriority);這句話:
getIServiceManager()獲取的是ServiceManagerProxy對象,參數obj是BinderProxy。

addService()

接着看最後一點(4/4),addService()
最後來看下ServiceManagerProxy中的相關方法(ServiceManagerProxy是ServiceManagerNative內部類),即getIServiceManager().addService():

ServiceManagerNative.java:
class ServiceManagerProxy implements IServiceManager {
    public ServiceManagerProxy(IBinder remote) {
        mRemote = remote;
    }
    
    public void addService(String name, IBinder service, boolean allowIsolated, int dumpPriority)
            throws RemoteException {
        Parcel data = Parcel.obtain();
        Parcel reply = Parcel.obtain();
        data.writeInterfaceToken(IServiceManager.descriptor);
        data.writeString(name);
        data.writeStrongBinder(service);
        data.writeInt(allowIsolated ? 1 : 0);
        data.writeInt(dumpPriority);
        mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0);
        reply.recycle();
        data.recycle();
    }
}

注意data.writeStrongBinder(service);這裏寫入的IBinder對象是AMS最初傳入的this,是Binder的實例,而不是BinderProxy。
這裏的mRemote即建立ServiceManagerProxy對象時傳入的BinderProxy。


下面就是開始進入binder驅動了,得耐心接着看了。

先看下writeStrongBinder()

這個寫入過程稍微注意下。

Parcel:
public final void writeStrongBinder(IBinder val) {
    nativeWriteStrongBinder(mNativePtr, val);
}
private static native void nativeWriteStrongBinder(long nativePtr, IBinder val);

frameworks/base/core/jni/android_os_Parcel.cpp:
{"nativeWriteStrongBinder",   "(JLandroid/os/IBinder;)V", (void*)android_os_Parcel_writeStrongBinder},

static void android_os_Parcel_writeStrongBinder(JNIEnv* env, jclass clazz, jlong nativePtr, jobject object)
{
    Parcel* parcel = reinterpret_cast<Parcel*>(nativePtr);
    if (parcel != NULL) {
        const status_t err = parcel->writeStrongBinder(ibinderForJavaObject(env, object));
        if (err != NO_ERROR) {
            signalExceptionForError(env, clazz, err);
        }
    }
}

frameworks/base/core/jni/android_util_Binder.cpp:
sp<IBinder> ibinderForJavaObject(JNIEnv* env, jobject obj)
{
    if (obj == NULL) return NULL;

    // Instance of Binder?
    if (env->IsInstanceOf(obj, gBinderOffsets.mClass)) {
        JavaBBinderHolder* jbh = (JavaBBinderHolder*)
            env->GetLongField(obj, gBinderOffsets.mObject);
        return jbh->get(env, obj);
    }

    // Instance of BinderProxy?
    if (env->IsInstanceOf(obj, gBinderProxyOffsets.mClass)) {
        return getBPNativeData(env, obj)->mObject;
    }

    ALOGW("ibinderForJavaObject: %p is not a Binder object", obj);
    return NULL;
}

class JavaBBinderHolder
{
public:
    sp<JavaBBinder> get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp<JavaBBinder> b = mBinder.promote();
        if (b == NULL) {
            b = new JavaBBinder(env, obj);
       ......
};

class JavaBBinder : public BBinder
{
    .....
}

上面已經說過,這裏的service就是AMS對象,即Binder實例。因此writeStrongBinder()寫入的service經過ibinderForJavaObject(env, object)封裝成JavaBBinder(也即BBinder)。即服務Service對象轉換成BBinder,傳入到binder驅動了。

parcel->writeStrongBinder(ibinderForJavaObject(env, object));
-->
Parcel.cpp:
status_t Parcel::writeStrongBinder(const sp<IBinder>& val)
{
    return flatten_binder(ProcessState::self(), val, this);
}

status_t flatten_binder(const sp<ProcessState>& /*proc*/,
    const sp<IBinder>& binder, Parcel* out)
{
    ......
    if (binder != nullptr) {
        BBinder *local = binder->localBinder();
        if (!local) {
            .......
        } else {
            obj.hdr.type = BINDER_TYPE_BINDER;
    .....

上面看到這裏binder是BBinder對象,注意這裏的hdr.type = BINDER_TYPE_BINDER ,在binder驅動中有使用。

mRemote.transact(ADD_SERVICE_TRANSACTION, data, reply, 0)

接着Java層今後開始向binder驅動傳遞

BinderProxy:
public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
    ......
     try {
        return transactNative(code, data, reply, flags);
    ......
}

public native boolean transactNative(int code, Parcel data, Parcel reply,
            int flags) throws RemoteException;
       
frameworks/base/core/jni/android_util_Binder.cpp:
{"transactNative",      "(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z", (void*)android_os_BinderProxy_transact},

static jboolean android_os_BinderProxy_transact(JNIEnv* env, jobject obj,
        jint code, jobject dataObj, jobject replyObj, jint flags) // throws RemoteException
{......
Parcel* data = parcelForJavaObject(env, dataObj);
Parcel* reply = parcelForJavaObject(env, replyObj);
......
IBinder* target = getBPNativeData(env, obj)->mObject.get();
......
status_t err = target->transact(code, *data, reply, flags);
......
}

parcelForJavaObject將data、reply兩個Parcel由Java對象轉換成C++。
getBPNativeData()獲取的是BpBinder對象。

接下來看BpBinder中的transact()。

frameworks/native/libs/binder/BpBinder.cpp:
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);
    ......
}

frameworks/native/libs/binder/IPCThreadState.cpp:
status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    ......
    err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, nullptr);
    err = waitForResponse(??);
    ......
}

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    tr.target.handle = handle;
    tr.code = code;
    ......
    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));

    return NO_ERROR;
}

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    ......
    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        ......
        cmd = (uint32_t)mIn.readInt32();
    .......
}
     
status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ......
    do {
        ......
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
        ......
    } while (err == -EINTR);
    ......
    if (bwr.read_consumed > 0) {
        mIn.setDataSize(bwr.read_consumed);
        mIn.setDataPosition(0);
    }
    ......
}

transact()中關鍵兩步,writeTransactionData()和waitForResponse()。
writeTransactionData()將要傳遞的數據及命令寫入到mOut。這裏要發送的命令是BC_TRANSACTION。 在注意的是,handle標識的是目標端,這裏是0。即註冊中目標是Servicemanager(handle 0 對應 binder_context_mgr_node對象)。
waitForResponse()中while(1)死循環,經過talkWithDriver()中ioctl進入binder,這裏傳入到binder_ioctl的參數cmd是BINDER_WRITE_READ。
waitForResponse()很重要,在死循環中會對binder返回的應答進行處理,cmd = (uint32_t)mIn.readInt32();獲取應答的命令類型。
另外,注意下傳入transact()中的flag爲0(即非TF_ONE_WAY)。

進入binder驅動

經過ioctl(),進入了binder內核

{kernel}/drivers/android/binder.c

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
    .....
    switch (cmd) {
        case BINDER_WRITE_READ:
            ret = binder_ioctl_write_read(filp, cmd, arg, thread);
            if (ret)
                goto err;
            break;
    ......
}

static int binder_ioctl_write_read(struct file *filp,
				unsigned int cmd, unsigned long arg,
				struct binder_thread *thread)
{
    ......
    if (copy_from_user(&bwr, ubuf, sizeof(bwr))) {
		ret = -EFAULT;
		goto out;
	}
    ......
    if (bwr.write_size > 0) {
		ret = binder_thread_write(proc, thread,
					  bwr.write_buffer,
					  bwr.write_size,
					  &bwr.write_consumed);
        ......
        if (copy_to_user(ubuf, &bwr, sizeof(bwr)))
				ret = -EFAULT;
			goto out;
    ......
    if (bwr.read_size > 0) {
		ret = binder_thread_read(proc, thread, bwr.read_buffer,
					 bwr.read_size,
					 &bwr.read_consumed,
					 filp->f_flags & O_NONBLOCK);
    ......
}

static int binder_thread_write(struct binder_proc *proc,
			struct binder_thread *thread,
			binder_uintptr_t binder_buffer, size_t size,
			binder_size_t *consumed)
{
    ......
    void __user *buffer = (void __user *)(uintptr_t)binder_buffer;
	void __user *ptr = buffer + *consumed;
    ......
    if (get_user(cmd, (uint32_t __user *)ptr))
    ......
    switch (cmd) {
    ......
    case BC_TRANSACTION:
    case BC_REPLY: {
        struct binder_transaction_data tr;

        if (copy_from_user(&tr, ptr, sizeof(tr)))
            return -EFAULT;
        ptr += sizeof(tr);
        binder_transaction(proc, thread, &tr,
                   cmd == BC_REPLY, 0);
        break;
    }
    ......
    }
}

經過系統調用,進入binder驅動的binder_ioctl()方法,這裏傳入的cmd是BINDER_WRITE_READ(),上面 BpBinder中的transact()有說。
上面 BpBinder中的transact()也說過發送命令在mOut中是BC_TRANSACTION,這時經過copy_from_user()從用戶空間拷貝數據到了內核空間。最終進入到binder_transaction()事務處理。
注意第四個參數cmd==BC_REPLY爲false

最重要的binder_transaction()

static void binder_transaction(struct binder_proc *proc,
			       struct binder_thread *thread,
			       struct binder_transaction_data *tr, int reply,
			       binder_size_t extra_buffers_size)
{
    .....
    if(reply){
    ......
    }else {
        if (tr->target.handle) {
        ......
        } else {
            ......
            target_node = context->binder_context_mgr_node;
            ......
        }
    }
    ......
        switch (hdr->type) {
            case BINDER_TYPE_BINDER:
            case BINDER_TYPE_WEAK_BINDER: {
                struct flat_binder_object *fp;

                fp = to_flat_binder_object(hdr);
    #ifdef BINDER_WATCHDOG
                ret = binder_translate_binder(tr, fp, t, thread);
    #else
                ret = binder_translate_binder(fp, t, thread);
    #endif
    ......
	tcomplete->type = BINDER_WORK_TRANSACTION_COMPLETE;
	t->work.type = BINDER_WORK_TRANSACTION;
	......
	if (!binder_proc_transaction(t, target_proc, 
}

#ifdef BINDER_WATCHDOG
static int binder_translate_binder(struct binder_transaction_data *tr,
......
{
    struct binder_node *node;
    node = binder_get_node(proc, fp->binder);
	if (!node) {
		node = binder_new_node(proc, fp);
		if (!node)
			return -ENOMEM;
#ifdef BINDER_WATCHDOG
		parse_service_name(tr, proc, node->name);
#endif
    ......
    ret = binder_inc_ref_for_node(target_proc, node,
			fp->hdr.type == BINDER_TYPE_BINDER,
			&thread->todo, &rdata);
    ......
	if (fp->hdr.type == BINDER_TYPE_BINDER)
		fp->hdr.type = BINDER_TYPE_HANDLE;
    fp->binder = 0;
	fp->handle = rdata.desc;
}

/* this is an addService() transaction identified by:
 * fp->type == BINDER_TYPE_BINDER && tr->target.handle == 0
 */
void parse_service_name(struct binder_transaction_data *tr,

binder_transaction()這個事務處理方法很長,這裏主要說下幾個注意點。
reply:前面流程傳入的爲false,cmd是BC_TRANSACTION。說明這是一個Client發給Server的請求事務,在Client端線程上。若爲true,便是BC_REPLY說明這是一個Server發給Client的事務處理回覆。在server端的線程上。
tr->target.handle:若是是BC_TRANSACTION(這裏註冊中是這個),接着判斷tr->target.handle。若是>0,即目標爲普通Service,若是爲0,則目標service是ServiceManager。從而獲取目標結點target_node,進一步獲取目標進程、目標線程及相關信息。
前面有講到傳遞的BBinder對象中hdr.type = BINDER_TYPE_BINDER。最終有走到binder_translate_binder,爲註冊服務建立了binder_node結點,保存了服務的進程及相關信息。

向servicemanager添加BINDER_WORK_TRANSACTION事務,接下來進入ServiceManager進程。

handle值(也待詳細瞭解//TODO):
binder_get_node()->binder_new_node()->binder_inc_ref_for_node()->binder_get_ref_for_node_olocked(),不詳述。
new_ref->data.desc,data.desc即handle。

handle值計算方法規律:
每一個進程binder_proc所記錄的binder_ref的handle值是從1開始遞增的;
全部進程binder_proc所記錄的handle=0的binder_ref都指向service manager;
同一個服務的binder_node在不一樣進程的binder_ref的handle值能夠不一樣;

接下來的註冊過程進入ServiceManager,從下面ServiceManager的建立過程瞭解。

ServiceManager的建立

ServiceManager自己也是Binder服務,但它經過自身的binder.c與Binder驅動直接通訊。經過循環binder_loop進行讀取和處理事務。
主要關注兩個文件:frameworks/native/cmds/servicemanager/service_manager.cframeworks/native/cmds/servicemanager/binder.c

系統啓動經過init.rc建立並啓動servicemanager。直接看其中main()方法。

frameworks/native/cmds/servicemanager/service_manager.c:
int main(int argc, char** argv)
{
    ......
    //打開binder驅動,申請128k字節大小的內存空間
    bs = binder_open(driver, 128*1024);
    ......
    if (binder_become_context_manager(bs)) {
    ......
    binder_loop(bs, svcmgr_handler);
    ......
}

重點須要關注的是上述3個方法,依次來看:

struct binder_state *binder_open(const char* driver, size_t mapsize)
{
    ......
    bs->fd = open(driver, O_RDWR | O_CLOEXEC);
    ......
    if ((ioctl(bs->fd, BINDER_VERSION, &vers) == -1) ||
        (vers.protocol_version != BINDER_CURRENT_PROTOCOL_VERSION)) {
    ......
    bs->mapped = mmap(NULL, mapsize, PROT_READ, MAP_PRIVATE, bs->fd, 0);
    ......
}

frameworks/native/cmds/servicemanager/binder.c:
int binder_become_context_manager(struct binder_state *bs)
{
    int result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR_EXT, &obj);

    // fallback to original method
    if (result != 0) {
        android_errorWriteLog(0x534e4554, "121035042");

        result = ioctl(bs->fd, BINDER_SET_CONTEXT_MGR, 0);
    }
}
void binder_loop(struct binder_state *bs, binder_handler func)
{
    ......
    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;

        res = ioctl(bs->fd, BINDER_WRITE_READ, &bwr);
        ......
        res = binder_parse(bs, 0, (uintptr_t) readbuf, bwr.read_consumed, func);
    ......
}

int binder_parse(struct binder_state *bs, struct binder_io *bio,
                 uintptr_t ptr, size_t size, binder_handler func)
{
    while (ptr < end) {
        uint32_t cmd = *(uint32_t *) ptr;
        case BR_TRANSACTION_SEC_CTX:
        case BR_TRANSACTION: {
        ......
                res = func(bs, &txn, &msg, &reply);
                if (txn.transaction_data.flags & TF_ONE_WAY) {
                    binder_free_buffer(bs, txn.transaction_data.data.ptr.buffer);
                } else {
                    binder_send_reply(bs, &reply, txn.transaction_data.data.ptr.buffer, res);
                }
     ......
}

void binder_send_reply(struct binder_state *bs,
......
{
    ......
    data.cmd_reply = BC_REPLY;
    ......
    binder_write(bs, &data, sizeof(data));
}

binder_open():這個比較簡單,經過系統調用在binder驅動中建立binder_proc對象,調用mmap()內存映射分配了128K的內存空間。
binder_become_context_manager():使servicemanager成爲上下文的管理者,建立了全局的binder_node對象binder_context_mgr_node。
binder_loop();這個是最重要的方法,進入死循環,等待Client端的請求。解析binder信息,此處參數ptr指向BC_ENTER_LOOPER,func指向svcmgr_handler。故有請求到來(如BR_TRANSACTION),則調用svcmgr_handler處理,處理完成後會發送BC_REPLY。


看看svcmgr_handler

frameworks/native/cmds/servicemanager/service_manager.c:
int svcmgr_handler(struct binder_state *bs,
                   struct binder_transaction_data_secctx *txn_secctx,
                   struct binder_io *msg,
                   struct binder_io *reply)
{
......
    switch(txn->code) {
    case SVC_MGR_GET_SERVICE:
    case SVC_MGR_CHECK_SERVICE:
        handle = do_find_service(s, len, txn->sender_euid, txn->sender_pid,
                        (const char*) txn_secctx->secctx);
        bio_put_ref(reply, handle);
    case SVC_MGR_ADD_SERVICE:
        if (do_add_service(bs, s, len, handle, txn->sender_euid, allow_isolated, dumpsys_priority,
                    txn->sender_pid, (const char*) txn_secctx->secctx))
    ......
    bio_put_uint32(reply, 0);
......
}

SVC_MGR_ADD_SERVICE就是從addService那拆解來的。SVC_MGR_GET_SERVICE相似。
ServiceManager最核心的兩個功能爲查詢和註冊服務:
註冊服務:do_add_service(),記錄服務名和handle信息,保存到svclist列表;
查詢服務:do_find_service(),根據服務名查詢相應的的handle信息。

這樣,服務就註冊到ServiceManager。可以被客戶端獲取。

客戶端獲取服務

獲取服務概述

同服務註冊同樣,先看下大體的流程圖。
binder_client

簡述:
客戶端經過binder驅動從servicemanager進程查詢到服務的handle,servicemanager進程一樣應答binder驅動,binder驅動經過處理,向客戶端返回正確的數據命令,客戶端從而獲取到服務的Binder對象。完成獲取服務的的操做。

獲取服務詳細過程

直接來看

ActivityManager.getService():

ActivityManager:
@UnsupportedAppUsage
public static IActivityManager getService() {
    return IActivityManagerSingleton.get();
}

@UnsupportedAppUsage
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;
            }
        };

ServiceManager.getService(Context.ACTIVITY_SERVICE):

ServiceManager:
@UnsupportedAppUsage
private static Map<String, IBinder> sCache = new ArrayMap<String, IBinder>();

@UnsupportedAppUsage
public static IBinder getService(String name) {
    try {
        IBinder service = sCache.get(name);
        if (service != null) {
            return service;
        } else {
            return Binder.allowBlocking(rawGetService(name));
        }
    } catch (RemoteException e) {
        Log.e(TAG, "error in getService", e);
    }
    return null;
}

private static IBinder rawGetService(String name) throws RemoteException {
    ......
    final IBinder binder = getIServiceManager().getService(name);
    ......
}

getIServiceManager()與註冊時的流程差很少,返回的是ServiceManagerProxy對象,不在依次贅述了。

直接看下getService()

ServiceManagerNative.java->
class ServiceManagerProxy:
@UnsupportedAppUsage
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;
}

mRemote.transact(GET_SERVICE_TRANSACTION, data, reply, 0);進入binder驅動的也與註冊相似。很少贅述。
這裏過程大體是,經過transact進入binder驅動,一樣找到的目標端是servicemanager,向servicemanager發送請求(BR_TRANSACTION)查詢服務(上述ServiceManager建立中),servicemanager查詢服務得到服務的handle,經過BC_REPLY返回到binder驅動。binder驅動得到服務的handle,最終一樣走到binder_transaction()。binder_thread_read()。

mRemote.transact()

下面是一些信息(do_find_service()查詢到服務handle後經過bio_put_ref迴應的一些信息,binder中進行處理的重要信息):

void bio_put_ref(struct binder_io *bio, uint32_t handle)
{
    ......
    obj->flags = 0x7f | FLAT_BINDER_FLAG_ACCEPTS_FDS;
    obj->hdr.type = BINDER_TYPE_HANDLE;
    obj->handle = handle;
    obj->cookie = 0;
}

最終進入binder_transaction()

static void binder_transaction(struct binder_proc *proc,
......
        case BINDER_TYPE_HANDLE:
		case BINDER_TYPE_WEAK_HANDLE: {
			struct flat_binder_object *fp;

			fp = to_flat_binder_object(hdr);
			ret = binder_translate_handle(fp, t, thread);   
			.....
			binder_alloc_copy_to_buffer(&target_proc->alloc,
						    t->buffer, object_offset,
						    fp, sizeof(*fp));
}

static int binder_translate_handle(struct flat_binder_object *fp,
......
    if (node->proc == target_proc) {
        ......
		if (fp->hdr.type == BINDER_TYPE_HANDLE)
			fp->hdr.type = BINDER_TYPE_BINDER;
		else
			fp->hdr.type = BINDER_TYPE_WEAK_BINDER;
		fp->binder = node->ptr;
		fp->cookie = node->cookie;
		......
    } else {
        ......
        ret = binder_inc_ref_for_node(target_proc, node,
				fp->hdr.type == BINDER_TYPE_HANDLE,
				NULL, &dest_rdata);
    }
}

經過上述方法依次走下去。在binder_translate_handle()中,node->proc == target_proc,當前是在servicemanager進程的,而目標進程是請求服務所在進程,因此等於判斷不成立。

這個過程很是重要,分兩種狀況來講:
當請求服務的進程與服務屬於不一樣進程,則爲請求服務所在進程建立binder_ref對象,指向服務進程中的binder_node;
當請求服務的進程與服務屬於同一進程,則再也不建立新對象,只是引用計數加1,而且修改type爲BINDER_TYPE_BINDER或BINDER_TYPE_WEAK_BINDER。

經過binder_thread_read進行一些處理。binder向客戶端發送BR_REPLY。

reply.readStrongBinder()

sp<IBinder> Parcel::readStrongBinder() const
{
    ALOGW("BINDER_DEBUG Parcel->readStrongBinder()");
    sp<IBinder> val;
    ......
    readNullableStrongBinder(&val);
    return val;
}

status_t Parcel::readNullableStrongBinder(sp<IBinder>* val) const
{
    ALOGW("BINDER_DEBUG Parcel->readNullableStrongBinder() val=%p", val);
    return unflatten_binder(ProcessState::self(), *this, val);
}

status_t unflatten_binder(const sp<ProcessState>& proc,
    const Parcel& in, sp<IBinder>* out)
{
    ALOGW("BINDER_DEBUG Parcel->unflatten_binder() sp<IBinder> begin");
    const flat_binder_object* flat = in.readObject(false);

    if (flat) {
        switch (flat->hdr.type) {
            case BINDER_TYPE_BINDER:
                *out = reinterpret_cast<IBinder*>(flat->cookie);
                return finish_unflatten_binder(nullptr, *flat, in);
            case BINDER_TYPE_HANDLE:
                *out = proc->getStrongProxyForHandle(flat->handle);
                return finish_unflatten_binder(
                    static_cast<BpBinder*>(out->get()), *flat, in);
        }
    }
    return BAD_TYPE;
}

由上面分析知道,servicemanager傳入的是BINDER_TYPE_HANDLE。請求服務與服務不在同一進程,這個值未變,還是BINDER_TYPE_HANDLE。getStrongProxyForHandle()註冊時有講過,這裏再也不單獨列出。這裏就獲取到了對應服務的BpBinder(handle)。handle是從servicemanager查到對應服務的handle。這樣服務獲取就完成了。

簡單總結

簡單回顧總結下幾個點

服務註冊與獲取大體過程

開始在 Binder---IPC 中所說的,服務註冊與獲取的大體過程:
binder_s_c
服務經過binder驅動註冊到ServiceManager,ServiceManager保存了服務的名稱、handle等信息 並加入svclist列表中。客戶端經過binder驅動向ServiceManager進程查詢獲取到對應的服務的handle,而後binder將信息返回給客戶端,客戶端獲取獲得相應的服務Binder。

與binder的交互命令

總結下 一個完整的服務註冊過程與binder交互命令大體以下圖:
add_service_cmd
服務的註冊和獲取基本相似,兩個過程,服務端都是ServiceManager。
Client端(BC_TRANSACTION)--->binder驅動(BR_TRANSACTION_COMPLETE)--->Client端; binder驅動(BR_TRANSACTION)--->Service端(BC_REPLY)--->binder驅動(BR_TRANSACTION_COMPLETE)--->Service端;binder驅動(BR_REPLY)--->Client端。

關於BpBinder、BBinder

總結下readStrongBinder():
請求服務進程與服務進程不在同一進程(如這個服務獲取),返回的是BpBinder對象。若是在同一進程,則不在建立新對象 只是引用加1,返回的是BBinder對象。


咱們經過handle去獲取遠程端的Binder對象,如handle爲0 就能獲取到servicemanager的BpBinder對象,經過查詢到的某個服務的handle獲取到對應服務的BpBinder對象(本地則是BBinder對象)。
在註冊時data.writeStrongBinder(service);,經過ibinderForJavaObject()將service實體binder對象轉換成BBinder,而後傳入binder驅動,完成服務註冊到servicemanager。


這裏的BBinder和BpBinder都是native層的Binder對象。 BBinder是本地Binder(Native Binder),BpBinder即遠程端Binder。
BpBinder提供transact()方法來發送請求;BBinder提供了onTransact()接口來接收請求。
BpBinder時客戶端建立用於消息發送的代理;BBinder是服務端用於接收消息的。當通訊時,Client端經過BinderProxy 經由Bpbinder的transact()方法最終發送請求到binder驅動。binder驅動接收到通過處理,發送給目標進程JavaBBinder,最終經由服務實體的onTransact()接受處理。
在註冊過程,servicemanager中svcmgr_handler()至關於服務端Java層的onTransact()。下面是普通服務接收到請求的過程:

frameworks/native/libs/binder/IPCThreadState.cpp
sp<BBinder> the_context_object;

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    ......
        default:
            err = executeCommand(cmd);
    ......
}

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    ......
    case BR_TRANSACTION_SEC_CTX:
    case BR_TRANSACTION:
        {
        ......
            if (tr.target.ptr) {
                ......
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,
                            &reply, tr.flags);
                ......
            } else {
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }
    ......
}

frameworks/native/libs/binder/Binder.cpp
status_t BBinder::transact(
......
            err = onTransact(code, data, reply, flags);
}

frameworks/base/core/jni/android_util_Binder.cpp
status_t onTransact(
    ......
        jboolean res = env->CallBooleanMethod(mObject, gBinderOffsets.mExecTransact,
            code, reinterpret_cast<jlong>(&data), reinterpret_cast<jlong>(reply), flags);
    ......
}

gBinderOffsets.mExecTransact = GetMethodIDOrDie(env, clazz, "execTransact", "(IJJI)Z");

frameworks/base/core/java/android/os/Binder.java
// Entry point from android_util_Binder.cpp's onTransact
@UnsupportedAppUsage
private boolean execTransact(int code, long dataObj, long replyObj,
......
   return execTransactInternal(code, dataObj, replyObj, flags, callingUid);
}

private boolean execTransactInternal(int code, long dataObj, long replyObj, int flags,
......
            res = onTransact(code, data, reply, flags);
}

這裏onTransact()最終調用到子類實現的onTransact(),即具體服務實現的onTransact()方法。

從上又有通常這樣的一個結構層次圖(網絡中不少,上述理解供參考):
binder_level

binder驅動中的幾個經常使用量

struct binder_node {
    ......
	struct binder_proc *proc;
	struct hlist_head refs;
}

binder_node--->binder結點,即binder的實體。服務註冊就會建立一個binder_node。
proc: binder_proc,這裏是binder實體對應的進程,至關於某個服務在哪進程。
refs: binder實體的引用對象列表,至關於全部使用某個服務的客戶端鏈表。

struct binder_ref {
	struct binder_ref_data data;
	struct binder_proc *proc;
	struct binder_node *node;
}

struct binder_ref_data {
	int debug_id;
	uint32_t desc;
	int strong;
	int weak;
};

binder_ref--->跟蹤結點的引用,binder_node的引用的信息
proc:引用對象進程,使用服務的進程
node:引用的binder_node,即引用的目標結點
desc:該引用對象的句柄(handle)

struct binder_proc {
	struct hlist_node proc_node;
	struct list_head todo;

}

binder_proc--->binder進程的上下文信息,每一個使用binder的進程都會建立一個binder_proc對象。在打開/dev/binder時就建立了。
proc_node:將該對象連接到全局binder_procs對象中。
todo:該進程的待處理事務隊列。

binder驅動結構體不少,須要多注意,不過都有註釋,理解不難。

相關文章
相關標籤/搜索