Android Binder跨进程源码解析

之前讲过Android Parcel数据传输源码解析,也讲过Android的bindService,但是Binder才是跨进程的核心内容,今天我就详细的说一下Binder到底是如何跨进程的。如果对bindService不是很了解的同学,建议先看看看上面的文章进行了解。

目录

1.Binder对象的创建

2.BinderProxy的创建

3.Binder对象的传输
​​​​​​​​​​​​​​

在跨进程通信之前,客服端client首先会执行bindService,和服务端进行连接,链接成功之后,会通过回调函数ServiceConnection的回调方法onServiceConnected将远程的IBinder对象进行返回,在我们自己写的通信接口类的Proxy中,赋值给mRemote。之后进行数据传输的时候,直接使用mRemote的transact方法进行跨进程通信。我相信小伙伴对上面的流程都比较熟悉了,但是不知道小伙伴思考过没,mRemote的具体实现类是谁?因为我们所能看见是mRemote是android.os.IBinder,它只是一个接口类,肯定有具体实现类的。

mRemote的具体实现类其实是BinderProxy,这个类在android.os.Binder.java类中。为什么是BinderProxy?我们在分析bindService的时候,没有找到BinderProxy的任何蛛丝马迹,怎么突然就变成了BinderProxy了呢?我们从头来说。

1.Binder对象的创建

AIDL生成了相关的接口类,而接口类中有一个Stub类,服务端Service中的onBind方法,返回的就是这个Stub对象,举例如下:

public static abstract class Stub extends android.os.Binder implements IBookManager {
        private static final String DESCRIPTOR = "com.example.bindertest.IBookManager";

        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }
        ....
}

继承了android.os.Binder类,我们看一下Binder类:

    public Binder() {
        init();
        ....
    }

    private native final void init();

init()是native方法,所以我们查看jni层的init方法,具体类为frameworks/base/core/jni/android_util_Binder.cpp

static void android_os_Binder_init(JNIEnv* env, jobject obj)
{
    JavaBBinderHolder* jbh = new JavaBBinderHolder();//注释1
    if (jbh == NULL) {
        jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
        return;
    }
    ALOGV("Java Binder %p: acquiring first ref on holder %p", obj, jbh);
    jbh->incStrong((void*)android_os_Binder_init);
    env->SetLongField(obj, gBinderOffsets.mObject, (jlong)jbh);//注释2
}

我们先看注释2:这是一个赋值操作,我们知道obj是Binder对象,那gBinderOffsets.mObject是什么呢?其实就是Binder中的mObject,注释2就是将JavaBBinderHolder赋值给了Binder的mObject,两者成为了一一对应的关系。

注释1的JavaBBinderHolder,创建JavaBBinderHolder的时候,会调用它的get方法:

sp<JavaBBinder> get(JNIEnv* env, jobject obj)
    {
        AutoMutex _l(mLock);
        sp<JavaBBinder> b = mBinder.promote();
        if (b == NULL) {
            b = new JavaBBinder(env, obj);//注释1
            mBinder = b;//注释2
            ALOGV("Creating JavaBinder %p (refs %p) for Object %p, weakCount=%" PRId32 "\n",
                 b.get(), b->getWeakRefs(), obj, b->getWeakRefs()->getWeakCount());
        }

        return b;
    }

注释1创建了JavaBBinder,并且在注释2中将JavaBBinder赋值给了mBinder,所以JavaBBinderHoldermBinder指向了JavaBBinder

我们再看一下JavaBBinder的构造方法:

    JavaBBinder(JNIEnv* env, jobject object)
        : mVM(jnienv_to_javavm(env)), mObject(env->NewGlobalRef(object))//注释1
    {
        ALOGV("Creating JavaBBinder %p\n", this);
        android_atomic_inc(&gNumLocalRefs);
        incRefsCreated(env);
    }

注释1这里将object赋值给了JavaBBinder的mObject,而object是Binder对象,所以mObject指向了Binder对象。

总结上述的关系如下:

Binder.mObject(Java层)----->JavaBBinderHolder(Native层)

JavaBBinderHolder.mBinder(Native层)----->JavaBBinder(Native层)

JavaBBinder.mObject(Native层)----->Binder(Java层)

2.BinderProxy的创建

对应关系是找到了,但是依然没有看见BinderProxy。我们都知道Binder对象是依靠ServiceConnection在两端传递的,但是它本身也仅仅是传递的作用,没有其他的发现。在看代码的时候,我发现AMS也是通过Binder进行跨进程通信的,那原理应该是一样的才对,所以我打算从AMS中进行线索的查找

我们看一下AMS对象的获取,在ActivityManager中:

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

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

我们先看注释2,这里和我们自己在使用AIDL通信的操作是一样的,都调用了Stub的asInterface方法,参数为远端的代理对象;我们再看注释1,这个远端的代理对象,是通过ServiceManager的getService获取到的,看一下ServiceManager的getService方法:

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

 先调用了getIserviceManager方法拿到了IServiceManager对象,然后调用IServiceManager的getService方法拿到了Binder对象。我们先看一下getIServiceManager方法:

    private static IServiceManager getIServiceManager() {
        if (sServiceManager != null) {
            return sServiceManager;
        }

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

我们可以看到,同样是调用了asInterface方法拿到了远端代理对象,而这个远端的代理对象时通过BinderInternal.getContextObject获取到的,看一下getContextObject方法:

public static final native IBinder getContextObject();

 是native方法,具体的实现在frameworks/base/core/jni/android_util_Binder.cpp中,如下:

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

 我们先看注释1的getContextObject方法,在frameworks/native/libs/binder/ProcessState.cpp中:

sp<IBinder> ProcessState::getContextObject(const sp<IBinder>& /*caller*/)
{
    return getStrongProxyForHandle(0);
}


sp<IBinder> ProcessState::getStrongProxyForHandle(int32_t handle)
{
    sp<IBinder> result;
    AutoMutex _l(mLock);
    handle_entry* e = lookupHandleLocked(handle);

    if (e != NULL) {
        IBinder* b = e->binder;
        if (b == NULL || !e->refs->attemptIncWeak(this)) {
            if (handle == 0) {
                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); //注释1
            e->binder = b;
            if (b) e->refs = b->getWeakRefs();
            result = b;//注释2
        } else {
            result.force_set(b);
            e->refs->decWeak(this);
        }
    }

    return result;
}

注释1创建了BpBinder对象,赋值给了注释2的result,然后进行了返回。

我们回到frameworks/base/core/jni/android_util_Binder.cpp中,看一下getContextObject方法中注释2的代码,第二个参数就是刚刚创建的BpBinder,我们看一下javaObjectForIBinder方法:

jobject javaObjectForIBinder(JNIEnv* env, const sp<IBinder>& val)
{
    if (val == NULL) return NULL;

    ....

    object = env->NewObject(gBinderProxyOffsets.mClass, gBinderProxyOffsets.mConstructor);//注释1
    if (object != NULL) {
        env->SetLongField(object, gBinderProxyOffsets.mObject, (jlong)val.get());
        val->incStrong((void*)javaObjectForIBinder);

        jobject refObject = env->NewGlobalRef(
                env->GetObjectField(object, gBinderProxyOffsets.mSelf));
        val->attachObject(&gBinderProxyOffsets, refObject,
                jnienv_to_javavm(env), proxy_cleanup);

        // Also remember the death recipients registered on this proxy
        sp<DeathRecipientList> drl = new DeathRecipientList;
        drl->incStrong((void*)javaObjectForIBinder);
        env->SetLongField(object, gBinderProxyOffsets.mOrgue, reinterpret_cast<jlong>(drl.get()));

        // Note that a new object reference has been created.
        android_atomic_inc(&gNumProxyRefs);
        incRefsCreated(env);
    }

    return object;
}

我们在注释1这里可以看到,通过反射的方式创建了gBinderProxyOffsets.mClass所代表的类对象,并且进行了返回,返回到了Java层,所以这类就是远端的代理对象。这个类估计大家也能猜到,就是BindProxy,为什么呢?其实这里设计到了Android系统的启动流程,这篇博客不涉及,所以我就不带着去找了,我总结了几个步骤作为参考:

第一步:app_main.cpp的main方法
第二步:AndroidRuntime的start方法
第三步:AndroidRuntime的startReg方法
第四步:AndroidRuntime的register_jni_procs方法
第五步:遍历gRegJNI数组,而android_util_Binder.cpp的register_android_os_Binder方法就在其中
第六步:执行android_util_Binder.cpp的int_register_android_os_Binder方法
第七步:对gBinderOffsets的成员变量赋值,其中:
(1)mClass为 android/os/Binder.java
(2)mExecTransact为 android/os/Binder.java这个类的execTransact方法
(3)mObject为 android/os/Binder.java这个类的mObject对象
第八步:对gBinderProxyOffsets的成员变量赋值,其中
(1)mClass为 android/os/BinderProxy,这个类在android/os/Binder.java中
(2)mConstructor为 android/os/BinderProxy的构造器
(3)mObject为 android/os/BinderProxy的mObject

3.Binder对象的传输

bindService这篇文章我们可以知道,Binder对象是通过IServiceConnection进行传输的,如下:

ActiveServices的publishServiceLocked方法

void publishServiceLocked(ServiceRecord r, Intent intent, IBinder service) {
        ...
        try {
            c.conn.connected(r.name, service);
        } catch (Exception e) {
            Slog.w(TAG, "Failure sending service " + r.name +" to connection " + c.conn.asBinder() +" (in " + c.binding.client.processName + ")", e);
        }
        ...
}

IServiceConnection具体代码我们看不见,但是我们大致可以猜到,IServiceConnection的原理是Binder跨进程通信机制,只有这样,才能实现跨进程的数据传输。很明显,c.conn.connected方法就是客户端client调用的方法,而真正进行跨进程通信的其实是服务端的代理类。也就是说,IServiceConnection中也有一个远端代理mRemote,而这个mRemote就是BinderProxy,我们的Binder对象,也是通过我们要验证的BinderProxy类进行传输的。我们查看BinderProxy的transact方法:

    public boolean transact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
        Binder.checkParcel(this, code, data, "Unreasonably large binder buffer");
        if (Binder.isTracingEnabled()) { Binder.getTransactionTracker().addTrace(); }
        return transactNative(code, data, reply, flags);
    }

    public native boolean transactNative(int code, Parcel data, Parcel reply,int flags) throws RemoteException;

transactNative方法是native方法,所以我们查看jni层的代码:

frameworks/base/core/jni/android_util_Binder.cpp

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);
    if (data == NULL) {
        return JNI_FALSE;
    }
    Parcel* reply = parcelForJavaObject(env, replyObj);
    if (reply == NULL && replyObj != NULL) {
        return JNI_FALSE;
    }

    IBinder* target = (IBinder*)env->GetLongField(obj, gBinderProxyOffsets.mObject);
    ...
    //printf("Transact from Java code to %p sending: ", target); data->print();
    status_t err = target->transact(code, *data, reply, flags);
    ....
}

第5行,第9行:拿到请求和响应的Parcel对象

第14行:obj就是BinderProxy对象,而gBinderProxyOffsets.mObject就是BinderProxy类中的mObject。所以这句代码就是拿到BinderProxy中的mObject对象。而mObject对象其实就是BpBinder(frameworks/native/libs/binder/BpBinder.cpp),而BpBinder与Java层的BinderProxy是一一对应的,这个我们稍后再证明

第17行:调用BpBinder的transact方法

我们查看BpBinder(frameworks/native/libs/binder/BpBinder.cpp)的transact方法

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

我们查看IPCThreadState(frameworks/native/libs/binder/IPCThreadState.cpp)的transact方法

status_t IPCThreadState::transact(int32_t handle,
                                  uint32_t code, const Parcel& data,
                                  Parcel* reply, uint32_t flags)
{
    ...
    if (err == NO_ERROR) {
        LOG_ONEWAY(">>>> SEND from pid %d uid %d %s", getpid(), getuid(),
            (flags & TF_ONE_WAY) == 0 ? "READ REPLY" : "ONE WAY");
        err = writeTransactionData(BC_TRANSACTION, flags, handle, code, data, NULL);
    }
    ...
    if ((flags & TF_ONE_WAY) == 0) {
        ...
        if (reply) {
            err = waitForResponse(reply);
        } else {
            Parcel fakeReply;
            err = waitForResponse(&fakeReply);
        }
        ...
    } else {
        err = waitForResponse(NULL, NULL);
    }
    return err;
}

这里有两个关键方法writeTransactionDatawaitForResponse,我们先看一下writeTransactionData方法

status_t IPCThreadState::writeTransactionData(int32_t cmd, uint32_t binderFlags,
    int32_t handle, uint32_t code, const Parcel& data, status_t* statusBuffer)
{
    binder_transaction_data tr;

    tr.target.ptr = 0; /* Don't pass uninitialized stack data to a remote process */
    tr.target.handle = handle;
    tr.code = code;
    tr.flags = binderFlags;
    tr.cookie = 0;
    tr.sender_pid = 0;
    tr.sender_euid = 0;

    const status_t err = data.errorCheck();
    if (err == NO_ERROR) {
        tr.data_size = data.ipcDataSize();
        tr.data.ptr.buffer = data.ipcData();
        tr.offsets_size = data.ipcObjectsCount()*sizeof(binder_size_t);
        tr.data.ptr.offsets = data.ipcObjects();
    } else if (statusBuffer) {
        tr.flags |= TF_STATUS_CODE;
        *statusBuffer = err;
        tr.data_size = sizeof(status_t);
        tr.data.ptr.buffer = reinterpret_cast<uintptr_t>(statusBuffer);
        tr.offsets_size = 0;
        tr.data.ptr.offsets = 0;
    } else {
        return (mLastError = err);
    }

    mOut.writeInt32(cmd);
    mOut.write(&tr, sizeof(tr));

    return NO_ERROR;
}

这个方法的作用,总结来说就是将binder_transaction_data结构体写入到Parcel对象mOut中。binder_transaction_data是用来描述Binder事务交互的数据结构体。它也属于内核空间和用户空间的通信结构体。个人理解,binder_transaction_data就是一个包裹类,用于通信的。

我们再看一下上面说的writeTransactionData:

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        err = mIn.errorCheck();
        if (err < NO_ERROR) break;
        if (mIn.dataAvail() == 0) continue;

        cmd = (uint32_t)mIn.readInt32();
        ...
    }
    ...

    return err;
}

我们可以看到,这里是一个死循环,等到talkWithDriver方法有结果返回,我们看一下talkWithDriver方法

status_t IPCThreadState::talkWithDriver(bool doReceive)
{
    ...
    binder_write_read bwr;
    // Is the read buffer empty?
    const bool needRead = mIn.dataPosition() >= mIn.dataSize();

    const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;

    bwr.write_size = outAvail;
    bwr.write_buffer = (uintptr_t)mOut.data();

    // This is what we'll read.
    if (doReceive && needRead) {
        bwr.read_size = mIn.dataCapacity();
        bwr.read_buffer = (uintptr_t)mIn.data();
    } else {
        bwr.read_size = 0;
        bwr.read_buffer = 0;
    }
    ...
    // Return immediately if there is nothing to do.
    if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;

    bwr.write_consumed = 0;
    bwr.read_consumed = 0;
    status_t err;
    do {
        ...
        if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)
            err = NO_ERROR;
        else
            err = -errno;
        ...
    } while (err == -EINTR);
    ...
    return err;
}

binder_write_read是内核空间和用户空间的通信结构体,它记录了Binder读写内容的相关信息。当用户空间的应用程序和Binder驱动通信时,它会将数据打包到binder_write_read中。write开头的是记录应用程序要发送给Binder驱动的内容,而read开头的是记录Binder驱动要反馈给应用程序的内容。参考博客

第30行代码:ioctl这个方法的具体实现是在内核层,需要看内核代码(官网地址,需要翻墙),我们看一下ioctl的具体代码:

在看内核代码之前,我们先了解几个概念:

binder_proc:是描述进程上下文信息的,每个用户的进程都对应binder_proc结构体。每当一个程序打开该文件节点时,Binder驱动中会新建一个binder_proc对象来保存改进程的上下文信息。

binder_thread:是描述Binder线程相关的结构体

在/dirvers/android/binder.c中,从framework层传过来的cmd是BINDER_WRITE_READ,所以我们只看BINDER_WRITE_READ相关的代码

static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	int ret;
	struct binder_proc *proc = filp->private_data;
	.....

	thread = binder_get_thread(proc);
	if (thread == NULL) {
		ret = -ENOMEM;
		goto err;
	}

	switch (cmd) {
	case BINDER_WRITE_READ:
		ret = binder_ioctl_write_read(filp, cmd, arg, thread);
		if (ret)
			goto err;
		break;
        ....
	}
	default:
		ret = -EINVAL;
		goto err;
	}
	....
	return ret;
}

第4行代码:获取binder_proc对象

第7行代码:获取binder_thread对象,也就是binder_proc所在的线程

看看binder_ioctl_write_read方法

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.read_size > 0) {
		ret = binder_thread_read(proc, thread, bwr.read_buffer,
					 bwr.read_size,
					 &bwr.read_consumed,
					 filp->f_flags & O_NONBLOCK);
		....
	}
	...
	if (copy_to_user(ubuf, &bwr, sizeof(bwr))) {
		ret = -EFAULT;
		goto out;
	}
out:
	return ret;
}

这里面有两个关键的方法

copy_from_user:将数据从用户空间拷贝到内核空间

copy_to_user:将数据从内核空间拷贝到用户空间

这两个方法完成了数据的跨进程操作

binder_thread_read方法我没有去深研究,所以我就不展开了,不过这个方法中有两处关键代码:

(1)cmd = BR_TRANSACTION:存储这个指令,之后再framework层会取出来

(2)tr.cookie = target_node->cookie:cookie跨进程通信中服务端的Stub对象,在Service中onBind方法返回的对象,那这个cookie是在哪里存储的呢?由于篇幅有限,这个我们以后再去验证

内核中代码执行完成之后,会去唤醒Framework中IPCThreadState的talkWithDriver方法,继续向下执行,而talkWIthDriver方法在waitForResponse方法中,我们继续看waitForResponse方法:

status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{
    uint32_t cmd;
    int32_t err;

    while (1) {
        if ((err=talkWithDriver()) < NO_ERROR) break;
        ...
        cmd = (uint32_t)mIn.readInt32();
        switch (cmd) {
        ....
        default:
            err = executeCommand(cmd);
            if (err != NO_ERROR) goto finish;
            break;
        }
    }
    ...

    return err;
}

cmd就是上面说的BR_TRANSACTION,所以执行executeCommand方法,看下这个方法:

status_t IPCThreadState::executeCommand(int32_t cmd)
{
    BBinder* obj;
    RefBase::weakref_type* refs;
    status_t result = NO_ERROR;

    switch ((uint32_t)cmd) {
    ...
    case BR_TRANSACTION:
        {
            binder_transaction_data tr;
            result = mIn.read(&tr, sizeof(tr));
           ...
            if (tr.target.ptr) {
                if (reinterpret_cast<RefBase::weakref_type*>(
                        tr.target.ptr)->attemptIncStrong(this)) {
                    error = reinterpret_cast<BBinder*>(tr.cookie)->transact(tr.code, buffer,&reply, tr.flags);
                    reinterpret_cast<BBinder*>(tr.cookie)->decStrong(this);
                } else {
                    error = UNKNOWN_TRANSACTION;
                }

            } else {
                error = the_context_object->transact(tr.code, buffer, &reply, tr.flags);
            }
            ...
        }
        break;
    ...

    return result;
}

第17行代码:上面说了,tr.cookie是我们的Stub对象,而它是BBinder(frameworks/native/libs/binder/BBinder.cpp)类型,所以我们先看BBinder中的transact方法

status_t BBinder::transact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    data.setDataPosition(0);

    status_t err = NO_ERROR;
    switch (code) {
        case PING_TRANSACTION:
            reply->writeInt32(pingBinder());
            break;
        default:
            err = onTransact(code, data, reply, flags);
            break;
    }

    if (reply != NULL) {
        reply->setDataPosition(0);
    }

    return err;
}

code是我们自己的code,每个通信方法的标识符,所以执行onTransact方法,而onTransact在具体的实现类中被复写了(这个地方涉及到了addService的相关原理,以后的博客我们来学习),所以可以理解为直接执行了我们自己Stub类中的onTransact方法。至此,数据完成了传输,从客户端传输到了服务端。

感谢技术大牛的博客作为参考!

参考文章:

Android Binder机制(二) Binder中的数据结构 | skywang

Android系统之Binder源代码情景分析_litao55555的博客-CSDN博客_binder源码分析

【Android】Binder机制及其源码解读_风起云涌~的博客-CSDN博客_android binder

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值