Android学习(三)Binder IPC机制(1)

Binder IPC机制

Binder机制结构图:

 

Android学习(三)Binder IPC机制(1)_第1张图片

ServiceManagerProxy中的所有服务接口都是static的,用户不用额外创建任何类对象就可以直接使用ServiceManager的功能。

首先看ServiceManagerJava)中getService的实现:

/* \Android4.4\frameworks\base\core\java\android\os\ServiceManager.java*/

private static HashMap sCache = new HashMap();à sCache作为缓存,加快查询速度

public static IBinder getService(String name) {

        try {

            IBinder service = sCache.get(name);à查询缓存

            if (service != null) {

                return service;à返回结果

            } else {

                return getIServiceManager().getService(name);

            }

        } catch (RemoteException e) {

            Log.e(TAG, "error in getService", e);

        }

        return null;

    }

 

 

/* \Android4.4\frameworks\base\core\java\android\os\ServiceManager.java*/

private static IServiceManager getIServiceManager() {

        if (sServiceManager != null) {

            return sServiceManager;

        }

 

        // Find the service manager

        sServiceManager = ServiceManagerNative.asInterface(BinderInternal.getContextObject());à获取IServiceManager

        return sServiceManager;

    }

 

/* \Android4.4\frameworks\base\core\java\android\os\ServiceManagerNative.java*/

static public IServiceManager asInterface(IBinder obj)

    {

        if (obj == null) {

            return null;

        }

        IServiceManager in =

            (IServiceManager)obj.queryLocalInterface(descriptor);

        if (in != null) {

            return in;

        }

       

        return new ServiceManagerProxy(obj);

    }

asInterface函数负责将一个Binder对象转换成IServiceManager并在必要是创建ServiceManagerProxy

这里的IBinder对象(obj)是通过BinderInternal.getContextObject()得到的。

asInterface函数的处理逻辑分为以下两部分:

  • queryLocalInterface:查询本地是否已经有IServiceManager存在

  • 如果没有查询到则创建IServiceManager

/* \Android4.4\frameworks\base\core\java\android\os\ServiceManagerNative.java*/

public ServiceManagerProxy(IBinder remote) {

        mRemote = remote;

    }

构造函数简单的记录IBinder对象。

/* \Android4.4\frameworks\base\core\java\android\os\ServiceManagerNative.java*/

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数据

  • IBinder .transact:利用IBindertransact将请求发出,而不用理会Binder驱动中openmmap以及Binder指令。所以IBinder中一定会在内部使用ProcessStateIPSThreadState来与Binder驱动通信

  • 获取结果

IBinder是一个接口的定义如下:

/* \Android4.4\frameworks\base\core\java\android\os\IBinder.java*/

public interface IBinder {

public IInterface queryLocalInterface(String descriptor);

public boolean transact(int code, Parcel data, Parcel reply, int flags)

        throws RemoteException;

 

在创建ServiceManagerProxy时,传入了一个IBinder对象,然后借助它的transact方法就可以方便的与Binder驱动通信了,这个对象是通过BinderInternal类获取的:

/* \Android4.4\frameworks\base\core\java\com\android\internal\os\BinderInternal.java*/

public class BinderInternal {

public static final native IBinder getContextObject();

这是一个native的方法,通过JNI调用本地代码实现,实现如下:

/* \Android4.4\frameworks\base\core\jni\android_util_Binder.cpp*/

static jobject android_os_BinderInternal_getContextObject(JNIEnv* env, jobject clazz)

{

    sp b = ProcessState::self()->getContextObject(NULL);

    return javaObjectForIBinder(env, b);

}

通过ProcessState创建对象然后转化为Java层的IBinder对象。

实现ProcessState的关键点在于:

  • 保证同一进程中只有一个ProcessState实例存在,而且只有在ProcessState对象创建时才打开Binder设备以及做内存映射

  • 向上次提供IPC服务

ProcessState的实现代码:

/* \Android4.4\frameworks\native\libs\binder\ProcessState.cpp*/

sp ProcessState::self()

{

    Mutex::Autolock _l(gProcessMutex);

    if (gProcess != NULL) {

        return gProcess;

    }

    gProcess = new ProcessState;

    return gProcess;

}

保证一个进程中只有一个ProcessState实例。

ProcessState的构造函数如下:

/* \Android4.4\frameworks\native\libs\binder\ProcessState.cpp*/

ProcessState::ProcessState()

    : mDriverFD(open_driver())àopen_driver()

    , mVMStart(MAP_FAILED)

    , mManagesContexts(false)

    , mBinderContextCheckFunc(NULL)

    , mBinderContextUserData(NULL)

    , mThreadPoolStarted(false)

    , mThreadPoolSeq(1)

{

    if (mDriverFD >= 0) {à成功打开/dev/binder

        // XXX Ideally, there should be a specific define for whether we

        // have mmap (or whether we could possibly have the kernel module

        // availabla).

#if !defined(HAVE_WIN32_IPC)

        // mmap the binder, providing a chunk of virtual address space to receive transactions.

        mVMStart = mmap(0, BINDER_VM_SIZE, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, mDriverFD, 0);à开始执行mmap,内存大小为:BINDER_VM_SIZE=(1*1024*1024 – (4096*2))

        if (mVMStart == MAP_FAILED) {

            // *sigh*

            ALOGE("Using /dev/binder failed: unable to mmap transaction memory.\n");

            close(mDriverFD);

            mDriverFD = -1;

        }

#else

        mDriverFD = -1;

#endif

    }

 

    LOG_ALWAYS_FATAL_IF(mDriverFD < 0, "Binder driver could not be opened.  Terminating.");

}

/* \Android4.4\frameworks\native\libs\binder\ProcessState.cpp*/

static int open_driver()

{

    int fd = open("/dev/binder", O_RDWR);

    if (fd >= 0) {

        fcntl(fd, F_SETFD, FD_CLOEXEC);

        int vers;

        status_t result = ioctl(fd, BINDER_VERSION, &vers);

        if (result == -1) {

            ALOGE("Binder ioctl to obtain version failed: %s", strerror(errno));

            close(fd);

            fd = -1;

        }

        if (result != 0 || vers != BINDER_CURRENT_PROTOCOL_VERSION) {

            ALOGE("Binder driver protocol does not match user space protocol!");

            close(fd);

            fd = -1;

        }

        size_t maxThreads = 15;

        result = ioctl(fd, BINDER_SET_MAX_THREADS, &maxThreads);

        if (result == -1) {

            ALOGE("Binder ioctl to set max threads failed: %s", strerror(errno));

        }

    } else {

        ALOGW("Opening '/dev/binder' failed: %s\n", strerror(errno));

    }

    return fd;

}

接下来查看如何创建IBinder对象的:

/* \Android4.4\frameworks\native\libs\binder\ProcessState.cpp*/

sp ProcessState::getContextObject(const sp& caller)

{

    return getStrongProxyForHandle(0);

}

 

实现函数:

/* \Android4.4\frameworks\native\libs\binder\ProcessState.cpp*/

sp ProcessState::getStrongProxyForHandle(int32_t handle)

{

    sp result;

 

    AutoMutex _l(mLock);

 

    handle_entry* e = lookupHandleLocked(handle);à查找一个vectormHandleToObject,这里保存了这个进程中已经创建的Binder相关信息

 

    if (e != NULL) {

        // We need to create a new BpBinder if there isn't currently one, OR we

        // are unable to acquire a weak reference on this current one.  See comment

        // in getWeakProxyForHandle() for more info about this.

        IBinder* b = e->binder;

        if (b == NULL || !e->refs->attemptIncWeak(this)) {

            if (handle == 0) {

                // Special case for context manager...

                // The context manager is the only object for which we create

                // a BpBinder proxy without already holding a reference.

                // Perform a dummy transaction to ensure the context manager

                // is registered before we create the first local reference

                // to it (which will occur when creating the BpBinder).

                // If a local reference is created for the BpBinder when the

                // context manager is not present, the driver will fail to

                // provide a reference to the context manager, but the

                // driver API does not return status.

                //

                // Note that this is not race-free if the context manager

                // dies while this code runs.

                //

                // TODO: add a driver API to wait for context manager, or

                // stop special casing handle 0 for context manager and add

                // a driver API to get a handle to the context manager with

                // proper reference counting.

 

                Parcel data;

                status_t status = IPCThreadState::self()->transact(

                        0, IBinder::PING_TRANSACTION, data, NULL, 0);

                if (status == DEAD_OBJECT)

                   return NULL;

            }

 

            b = new BpBinder(handle); à BpBinder的创建

            e->binder = b;

            if (b) e->refs = b->getWeakRefs();

            result = b;

        } else {

            // This little bit of nastyness is to allow us to add a primary

            // reference to the remote proxy when this team doesn't have one

            // but another team is sending the handle to us.

            result.force_set(b);

            e->refs->decWeak(this);

        }

    }

 

    return result;

}

ProcessState中有一个全局列表来记录所有与Binder对象相关的信息,每个表都是一个handle_entry结构体,代码如下:

/* \Android4.4\frameworks\native\libs\binder\ProcessState.h*/

struct handle_entry {

                IBinder* binder;

                RefBase::weakref_type* refs;

            };

其中binder属性实际上是一个BpBinder,只有在两种情况下才会生成一个BpBinder

  • 在列表中没有找到对应的BpBinder

  • 虽然从列表中查找到了对应的节点,但是没有办法顺利对这个BpBinder增减weakreference

 

 

转载于:https://my.oschina.net/honeyandroid/blog/504566

你可能感兴趣的:(Android学习(三)Binder IPC机制(1))