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进程处理
处理完按照原来的路径返回
这样就完成了一次跨进程通信