Binder机制原理学习

一个进程 会被分为两个空间 用户空间和内核空间 其中用户空间是隔离的 但内核空间是共享的

所以进程间通讯可以使用共享内核空间来进行

首先搞清楚一个概念 跨进程是一个比较泛的概念 有个统一的名字 IPC (Inter-Process Communication​)

Inter-Process Communication

简单的Inter-Process Communication的示意图如下

需要两次拷贝
而Binder 也是IPC的一种 是Android独有的

搞清楚inter-process communication概念之后 来讲讲Binder的一些概念

Binder驱动可以看做是个电话线 用户空间发送数据 进行一次拷贝 copy_form_user 将数据拷贝到内核缓存区

然后建立一个接收缓存区 和这个内核缓冲区进行内存映射 接受缓存区和服务进程又存在映射关系 所以 执行一次copy_from_user 就等于把数据传给了接受方

看下这张图

题外话:

查了一下资料 ServiceManager进程是个独立进程 是系统级别的进程 不是zygote派生出来的进程 这个进程没法杀死掉 即使kill之后 还会重启 相当于https的443端口 (其实也不能这么讲咯)

我上手试了一下 adb shell pidof servicemanager 打印出来的是 732 也就是我的测试机的ServiceManager的进程id 是732

大模型查了一下 kill这个 732 可能会导致系统崩掉 在不具备刷系统的情况下 还是不尝试了

我重启了一下手机 看看 这个pid 是否会变 命令adb reboot​

等系统重启成功 再次运行 adb shell pidof servicemanager​

返回还是732

下面继续 -->

Android 代码实现一个跨进程通讯

第一步创建一个 AIDL文件

// IMyAidlInterface.aidl
package com.nicestars.aidldemo;

// Declare any non-default types here with import statements

interface IMyAidlInterface {
    int add(int a, int b);
}

再去创建一个Service

package com.nicestars.aidldemo

import android.app.Service
import android.content.Intent
import android.os.IBinder

class MyService : Service() {

    private val binder =object :IMyAidlInterface.Stub(){
        override fun add(a: Int, b: Int): Int {
           return a+b
        }

    }

    override fun onBind(intent: Intent?): IBinder {
        return binder
    }
}

要在AndroidManifest文件里面注册一下服务

 <!-- 表示运行在独立子进程 -->
        <service
            android:name=".MyService"
            android:exported="true"
            android:process=":remote">
            <intent-filter>
                <action android:name="com.nicestars.aidldemo.MyService" />
            </intent-filter>
        </service>

客户端代码

package com.nicestars.aidldemo

import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Bundle
import android.os.IBinder
import android.util.Log
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity


class MainActivity : AppCompatActivity() {
    private var aidlInterface: IMyAidlInterface? = null

    private val connection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            aidlInterface = IMyAidlInterface.Stub.asInterface(service)
            val result = aidlInterface?.add(10, 20)
            Log.d("NiceStarsAIDL", "调用 add(10, 20) = $result")
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            aidlInterface = null
        }
    }


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)


        // 启动并绑定 Service
        val intent = Intent()
        intent.setClassName(this, "com.nicestars.aidldemo.MyService")
        bindService(intent, connection, BIND_AUTO_CREATE)


    }


    override fun onDestroy() {
        super.onDestroy()

        unbindService(connection)
    }
}

下面就是最精彩的代码拆解环节

MainActivity怎么和Service进行跨进程通讯的

首先 第一步 MyService要注册到ServiceManager进程 在哪一步呢

 override fun onBind(intent: Intent?): IBinder {
        return binder
    }


 // 启动并绑定 Service
        val intent = Intent()
        intent.setClassName(this, "com.nicestars.aidldemo.MyService")
        bindService(intent, connection, BIND_AUTO_CREATE)

然后要去获取服务 获取服务是在客户端获取的服务

override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
            aidlInterface = IMyAidlInterface.Stub.asInterface(service)
            val result = aidlInterface?.add(10, 20)
            Log.d("NiceStarsAIDL", "调用 add(10, 20) = $result")
        }

这样,客户端和服务端通过Binder驱动在ServiceManager侧产生了联系 Binder驱动 会在内核空间创建映射内存

接下来讲讲 AIDL文件的作用

简单一点讲 AIDL文件 是客户端和服务端通信的一个协议 规定了能做哪些类型的通信

下面来分析一下系统生成的IMyAidlInterface代码

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package com.nicestars.aidldemo;

// Declare any non-default types here with import statements
public interface IMyAidlInterface extends android.os.IInterface {
    /**
     * Default implementation for IMyAidlInterface.
     */
    public static class Default implements com.nicestars.aidldemo.IMyAidlInterface {
        @Override
        public int add(int a, int b) throws android.os.RemoteException {
            return 0;
        }

        @Override
        public android.os.IBinder asBinder() {
            return null;
        }
    }

    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.nicestars.aidldemo.IMyAidlInterface {
        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.nicestars.aidldemo.IMyAidlInterface interface,
         * generating a proxy if needed.
         */

        public static com.nicestars.aidldemo.IMyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.nicestars.aidldemo.IMyAidlInterface))) {
                return ((com.nicestars.aidldemo.IMyAidlInterface) iin);
            }
            return new com.nicestars.aidldemo.IMyAidlInterface.Stub.Proxy(obj);
        }


        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
                data.enforceInterface(descriptor);
            }
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
            }
            switch (code) {
                case TRANSACTION_add: {
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    break;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
            return true;
        }

        private static class Proxy implements com.nicestars.aidldemo.IMyAidlInterface {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

    public static final java.lang.String DESCRIPTOR = "com.nicestars.aidldemo.IMyAidlInterface";

    public int add(int a, int b) throws android.os.RemoteException;
}

第一步

​IMyAidlInterface extends android.os.IInterface​ 属于接口的继承 那么 IMyAidlInterface​结口就包含两个未实现方法

    public static class Default implements com.nicestars.aidldemo.IMyAidlInterface {
        @Override
        public int add(int a, int b) throws android.os.RemoteException {
            return 0;
        }

        @Override
        public android.os.IBinder asBinder() {
            return null;
        }
    }

接着 新建一个 Stub抽象类

    public static abstract class Stub extends android.os.Binder implements com.nicestars.aidldemo.IMyAidlInterface {
        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.nicestars.aidldemo.IMyAidlInterface interface,
         * generating a proxy if needed.
         */

        public static com.nicestars.aidldemo.IMyAidlInterface asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.nicestars.aidldemo.IMyAidlInterface))) {
                return ((com.nicestars.aidldemo.IMyAidlInterface) iin);
            }
            return new com.nicestars.aidldemo.IMyAidlInterface.Stub.Proxy(obj);
        }


        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        @Override
        public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException {
            java.lang.String descriptor = DESCRIPTOR;
            if (code >= android.os.IBinder.FIRST_CALL_TRANSACTION && code <= android.os.IBinder.LAST_CALL_TRANSACTION) {
                data.enforceInterface(descriptor);
            }
            switch (code) {
                case INTERFACE_TRANSACTION: {
                    reply.writeString(descriptor);
                    return true;
                }
            }
            switch (code) {
                case TRANSACTION_add: {
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    int _result = this.add(_arg0, _arg1);
                    reply.writeNoException();
                    reply.writeInt(_result);
                    break;
                }
                default: {
                    return super.onTransact(code, data, reply, flags);
                }
            }
            return true;
        }

        private static class Proxy implements com.nicestars.aidldemo.IMyAidlInterface {
            private android.os.IBinder mRemote;

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }

            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            }

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }

            @Override
            public int add(int a, int b) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(a);
                    _data.writeInt(b);
                    boolean _status = mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }

        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }

里面又包含了一个 Proxy的代理类 同样也实现了 IMyAidlInterface

定义了一个mRemote对象 将系统的IBinder复制给remote

这样 客户端和服务端都可以通过这个binder驱动对象来进行数据传递了

具体流程看下图

客户端通过代理对象将序列化之后的数据发送给Binder驱动 Binder驱动找到注册在ServiceManager的service进程 把数据给service进程处理
处理完按照原来的路径返回

这样就完成了一次跨进程通信


Binder机制原理学习
https://nicestars.net//archives/binderji-zhi-yuan-li-xue-xi
作者
NiceStars
发布于
2025年04月26日
更新于
2025年04月26日
许可协议