安卓AIDL和binder机制

本文详细介绍了Android中的AIDL(Android Interface Definition Language)和Binder机制。AIDL用于实现不同进程间的通信,支持多种数据类型,并通过生成的Stub类实现 Binder 的回调。Binder是Android的IPC框架,保证了应用层与系统服务的安全、稳定通信。文章探讨了Binder的工作原理,包括C/S架构、Binder驱动的角色以及进程间通信的具体流程,展示了Binder如何减少数据拷贝,提高通信效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、AIDL(Android Interface Definition Language,安卓接口定义语言)

1. AIDL 概念

不同程序和不同进程【即不同工程】之间的通信

设计AIDL这门语言的目的就是为了实现进程间通信。在Android系统中,每个进程都运行在一块独立的内存中,在其中完成自己的各项活动,与其他进程都分隔开来。可是有时候我们又有应用间进行互动的需求,比较传递数据或者任务委托等,AIDL就是为了满足这种需求而诞生的。通过AIDL,可以在一个进程中获取另一个进程的数据和调用其暴露出来的方法,从而满足进程间通信的需求。

AIDL 语法很简单,只是定义两个进程间的通信接口而已

而生成符合通信协议的 Java 代码则是由 Android SDK 的 platform-tools/aidl.exe 工具生成

生成对应的接口文件在: java(generated) 目录下,一般是 Xxx.java 的接口

在该接口中包含一个 Stub 的内部类,该类中实现了在该类中实现了 IBinder 接口与自定义的通信接口

Sub 类会作为远程 Service 的回调类——实现了 IBinder 接口,所以可作为 Service 的 onBind() 方法的返回值

创建 AIDL 文件:

2. AIDL 支持的数据类型

  1. java 的 8 种数据类型:byte、short、int、long、float、double、boolean、char
  2. 除此之外支持 String、charSequence、List、Map
  3. 自定义数据类型,实现Parcelabel的引用类型。

如果业务方法中参数或返回值类型为 List 或 Map 时:

List 中的所有元素都必须是 AIDL 支持的数据类型、其他 AIDL 生成的接口或自己声明的可打包类型。可选择将 List 用作“通用”类(例如,List<String>)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。

3, 创建AIDL

在工程的 src 目录下创建 .aidl 文件:

Book.aidl  -没有定义方法

// Book.aidl
package com.example.newdemo.myaidlserver;

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

parcelable Book;

BookController.aidl  指定了方法

// BookControler.aidl
package com.example.newdemo.myaidlserver;

import com.example.newdemo.myaidlserver.Book;

// 用于在不同进程中,获取 书籍信息和 添加书籍信息

interface BookControler {

// 获取书籍
    List<Book> getBoolList();

    void addBookInout(inout Book book); // 双向处理数据

    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}

点击  工具栏中  Build  --->  make project  ,Android SDK 工具会在相应的目录生成对应的与 .aidl 文件同名的 .java 接口文件

 BookControler接口信息如下:

/*
 * This file is auto-generated.  DO NOT MODIFY.
 */
package com.example.newdemo.myaidlserver;
// 用于在不同进程中,获取 书籍信息和 添加书籍信息

public interface BookControler extends android.os.IInterface
{
  /** Default implementation for BookControler. */
  public static class Default implements com.example.newdemo.myaidlserver.BookControler
  {
    // 获取书籍

    @Override public java.util.List<com.example.newdemo.myaidlserver.Book> getBoolList() throws android.os.RemoteException
    {
      return null;
    }
    @Override public void addBookInout(com.example.newdemo.myaidlserver.Book book) throws android.os.RemoteException
    {
    }
    // 双向处理数据

    @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
    {
    }
    @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.example.newdemo.myaidlserver.BookControler
  {
    private static final java.lang.String DESCRIPTOR = "com.example.newdemo.myaidlserver.BookControler";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }
    /**
     * Cast an IBinder object into an com.example.newdemo.myaidlserver.BookControler interface,
     * generating a proxy if needed.
     */
    public static com.example.newdemo.myaidlserver.BookControler asInterface(android.os.IBinder obj)
    {
      if ((obj==null)) {
        return null;
      }
      android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
      if (((iin!=null)&&(iin instanceof com.example.newdemo.myaidlserver.BookControler))) {
        return ((com.example.newdemo.myaidlserver.BookControler)iin);
      }
      return new com.example.newdemo.myaidlserver.BookControler.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;
      switch (code)
      {
        case INTERFACE_TRANSACTION:
        {
          reply.writeString(descriptor);
          return true;
        }
        case TRANSACTION_getBoolList:
        {
          data.enforceInterface(descriptor);
          java.util.List<com.example.newdemo.myaidlserver.Book> _result = this.getBoolList();
          reply.writeNoException();
          reply.writeTypedList(_result);
          return true;
        }
        case TRANSACTION_addBookInout:
        {
          data.enforceInterface(descriptor);
          com.example.newdemo.myaidlserver.Book _arg0;
          if ((0!=data.readInt())) {
            _arg0 = com.example.newdemo.myaidlserver.Book.CREATOR.createFromParcel(data);
          }
          else {
            _arg0 = null;
          }
          this.addBookInout(_arg0);
          reply.writeNoException();
          if ((_arg0!=null)) {
            reply.writeInt(1);
            _arg0.writeToParcel(reply, android.os.Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
          }
          else {
            reply.writeInt(0);
          }
          return true;
        }
        case TRANSACTION_basicTypes:
        {
          data.enforceInterface(descriptor);
          int _arg0;
          _arg0 = data.readInt();
          long _arg1;
          _arg1 = data.readLong();
          boolean _arg2;
          _arg2 = (0!=data.readInt());
          float _arg3;
          _arg3 = data.readFloat();
          double _arg4;
          _arg4 = data.readDouble();
          java.lang.String _arg5;
          _arg5 = data.readString();
          this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);
          reply.writeNoException();
          return true;
        }
        default:
        {
          return super.onTransact(code, data, reply, flags);
        }
      }
    }
    private static class Proxy implements com.example.newdemo.myaidlserver.BookControler
    {
      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 java.util.List<com.example.newdemo.myaidlserver.Book> getBoolList() throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        java.util.List<com.example.newdemo.myaidlserver.Book> _result;
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          boolean _status = mRemote.transact(Stub.TRANSACTION_getBoolList, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            return getDefaultImpl().getBoolList();
          }
          _reply.readException();
          _result = _reply.createTypedArrayList(com.example.newdemo.myaidlserver.Book.CREATOR);
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
        return _result;
      }
      @Override public void addBookInout(com.example.newdemo.myaidlserver.Book book) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          if ((book!=null)) {
            _data.writeInt(1);
            book.writeToParcel(_data, 0);
          }
          else {
            _data.writeInt(0);
          }
          boolean _status = mRemote.transact(Stub.TRANSACTION_addBookInout, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().addBookInout(book);
            return;
          }
          _reply.readException();
          if ((0!=_reply.readInt())) {
            book.readFromParcel(_reply);
          }
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      // 双向处理数据

      @Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException
      {
        android.os.Parcel _data = android.os.Parcel.obtain();
        android.os.Parcel _reply = android.os.Parcel.obtain();
        try {
          _data.writeInterfaceToken(DESCRIPTOR);
          _data.writeInt(anInt);
          _data.writeLong(aLong);
          _data.writeInt(((aBoolean)?(1):(0)));
          _data.writeFloat(aFloat);
          _data.writeDouble(aDouble);
          _data.writeString(aString);
          boolean _status = mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);
          if (!_status && getDefaultImpl() != null) {
            getDefaultImpl().basicTypes(anInt, aLong, aBoolean, aFloat, aDouble, aString);
            return;
          }
          _reply.readException();
        }
        finally {
          _reply.recycle();
          _data.recycle();
        }
      }
      public static com.example.newdemo.myaidlserver.BookControler sDefaultImpl;
    }
    static final int TRANSACTION_getBoolList = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    static final int TRANSACTION_addBookInout = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);
    static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);
    public static boolean setDefaultImpl(com.example.newdemo.myaidlserver.BookControler impl) {
      // Only one user of this interface can use this function
      // at a time. This is a heuristic to detect if two different
      // users in the same process use this function.
      if (Stub.Proxy.sDefaultImpl != null) {
        throw new IllegalStateException("setDefaultImpl() called twice");
      }
      if (impl != null) {
        Stub.Proxy.sDefaultImpl = impl;
        return true;
      }
      return false;
    }
    public static com.example.newdemo.myaidlserver.BookControler getDefaultImpl() {
      return Stub.Proxy.sDefaultImpl;
    }
  }
  // 获取书籍

  public java.util.List<com.example.newdemo.myaidlserver.Book> getBoolList() throws android.os.RemoteException;
  public void addBookInout(com.example.newdemo.myaidlserver.Book book) throws android.os.RemoteException;
  // 双向处理数据

  public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;
}

Stub 实现了本地接口且继承了 Binder 对象,介于 Binder 对象在系统底层的支持下,Stub 对象就具有了远程传输数据的能力,在生成 Stub 对象的时候会调用 asInterface 方法

  public static abstract class Stub extends android.os.Binder implements com.example.newdemo.myaidlserver.BookControler
  {
    private static final java.lang.String DESCRIPTOR = "com.example.newdemo.myaidlserver.BookControler";
    /** Construct the stub at attach it to the interface. */
    public Stub()
    {
      this.attachInterface(this, DESCRIPTOR);
    }

 

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

 链接

4. 参数修饰符

  • in: 表示参数数据只能由客户端传递到服务端,基本类型就默认只支持in修饰符。
  • out:表示参数数据只能由服务端传递到客户端。即服务端如果修改了参数对象的值,那么客户端的值也会变化,但是服务端无法读取到客户端对象的值。
  • inout:表示参数数据能够双向传递。

具体使用详情可以查看:AIDL详细解释

 

二、Binder机制

图解binder机制

1. 产生的背景

Android 很多核心功能都是由一系列 Services 支持的,比如 ActivityService、WindowService 等等等等,应用需要频繁地与这些 Services 发生交互,正是基于这种场景,就亟需一种好的 IPC 解决方案。

在这里插入图片描述

 

拿Activity举例从上图可以看出来:Activity是由ActivityManager来控制的,而ActivityManager其实是通过Binder获取ActivityManagerService服务来控制Activity的,并且ActivityManager是Android系统FrameWork层的,和应用中的activity不是同一个进程。

重点

1、Binder是Android提供的一套进程间通信框架。

2、系统服务ActivityManagerService,LocationManagerService,等都是在单独进程中的,使用binder和应用进行通信。

在这里插入图片描述

 

如上图,Android系统分成三层。最上层是application应用层,第二层是Framework层,第三层是native层。 由下图可知几点:

 

1、Android中的应用层和系统服务层不在同一个进程,系统服务在单独的进程中。

2、Android中不同应用属于不同的进程中。

Android应用和系统services运行在不同进程中是为了安全,稳定,以及内存管理的原因,但是应用和系统服务需要通信和分享数据。

优点

安全性:每个进程都单独运行的,可以保证应用层对系统层的隔离。

稳定性:如果某个进程崩溃了不会导致其他进程崩溃。

内存分配:如果某个进程以及不需要了可以从内存中移除,并且回收相应的内存。

2. Binder工作原理

可以把 Binder 驱动看作一个机器,它连接着所有 Services(假设 app 只调用 Services 提供的接口)。

一个 app(客户端)想要找一个 Service 办点事,它就要去操作这个机器,而这个机器会检测 app 的身份,如果身份合法,则可以继续操作。假设 app 要调用 A 服务的 foo 函数,那么它可以告诉这个机器,这个机器随后就会检查连在它身上的所有 Services,找到 app 需要的那一个,让它执行 foo 函数,并且再将返回值告诉 app,这样 app 就成功隔着进程操作到 A 服务了。

这当然是很抽象的说法,系统在 Framework 层做了很好地封装,让我们可以友好地使用 Binder 驱动来进行 IPC 操作

2.1 binder架构

a:Binder通信采用C/S架构,从组件视图来看,包含Client,Server,Binder驱动和ServicerManager,其中ServicerManager负责管理各种服务

b:Binder在Framework层进行了封装,通过JNI技术调用Native层的Binder架构

c:Binder在Native层通过ioctl方式与Binder驱动通信

binder的客户端和服务端通信原理的很好的例子


2.2 Binder通信模式

示意图

Binder基于C/S的结构下,定义了4个角色:Server、Client、ServerManager、Binder驱动,其中前三者是在用户空间的,也就是彼此之间无法直接进行交互,Binder驱动是属于内核空间的,属于整个通信的核心,虽然叫驱动,但是实际上和硬件没有太大关系,只是实现的方式和驱动差不多,驱动负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据包在进程之间的传递和交互等一系列底层支持。

Binder本质上只是提供了一种通信的方式,和我们具体要实现的内容没有关系,为了实现这个服务,我们需要定义一些接口,让client能够远程调用服务,因为是跨进程,这时候就要设计到代理模式,以接口函数位基准,client和server去实现接口函数,Server是服务真正的实现,client作为一个远程的调用。

  • 从Server进程来看,Binder是存在的实体对象,client通过transact()函数,经过Binder驱动,最终回调到Binder实体的onTransact()函数中。
  • 从 Client进程的角度看,Binder 指的是对 Binder 代理对象,是 Binder 实体对象的一个远程代理,通过Binder驱动进行交互

3 进程间通信的一个例子

为什么 IMyService 要分 StubProxy 呢?这是为了要适用于本地调用和远程调用两种情况。如果 Service 运行在同一个进程,那就直接用 Stub,因为它直接实现了 Service 提供的功能,不需要任何 IPC 过程。如果 Service 运行在其他进程,那客户端使用的就是 Proxy,这里这个 Proxy 的功能大家应该能想到了吧,就是把参数封装后发送给 Binder 驱动,然后执行一系列 IPC 操作最后再取出结果返回。

 

1. 定义一个接口服务,一个接口继承IInterface,代表了服务端的能力

public interface PersonManger extends IInterface {
    void addPerson(Person mPerson);
    List<Person> getPersonList();
}

2. 定义一个Server中的Binder实体对象,继承Binder类,实现上述服务端接口

public abstract class BinderObj extends Binder implements PersonManger {
    public static final String DESCRIPTOR = "com.example.taolin.hellobinder";
    public static final int TRANSAVTION_getPerson = IBinder.FIRST_CALL_TRANSACTION;
    public static final int TRANSAVTION_addPerson = IBinder.FIRST_CALL_TRANSACTION + 1;
    public static PersonManger asInterface(IBinder mIBinder){
        IInterface iInterface = mIBinder.queryLocalInterface(DESCRIPTOR);
        if (null!=iInterface&&iInterface instanceof PersonManger){
            return (PersonManger)iInterface;
        }
        return new Proxy(mIBinder);
    }
    @Override
    protected boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) throws RemoteException {
        switch (code){
            case INTERFACE_TRANSACTION:
                reply.writeString(DESCRIPTOR);
                return true;

            case TRANSAVTION_getPerson:
                data.enforceInterface(DESCRIPTOR);
                List<Person> result = this.getPersonList();
                reply.writeNoException();
                reply.writeTypedList(result);
                return true;

            case TRANSAVTION_addPerson:
                data.enforceInterface(DESCRIPTOR);
                Person arg0 = null;
                if (data.readInt() != 0) {
                    arg0 = Person.CREATOR.createFromParcel(data);
                }
                this.addPerson(arg0);
                reply.writeNoException();
                return true;
        }
        return super.onTransact(code, data, reply, flags);

    }

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

2.1 asInterface方法:

Binder驱动传来的IBinder对象,通过queryLocalInterface方法,查找本地Binder对象,

如果返回的就是PersonManger,说明client和server处于同一个进程,直接返回,

如果不是,返回给一个代理对象,说明不是在同一个进程。

2.2 onTransact 方法:

在Server进程里面,onTransact根据调用code会调用相关函数,接着将结果写入reply并通过super.onTransact返回给驱动,驱动唤醒挂起的Client进程里面的线程并将结果返回

boolean onTransact(int code, Parcel data, Parcel reply, int flags);

 // 作用:执行Client进程所请求的目标方法(子类需要复写)

// 参数说明:  code:Client进程请求方法标识符。即Server进程根据该标识确定所请求的目标方法

// data:目标方法的参数。(Client进程传进来的,此处就是整数a和b)

// reply:目标方法执行后的结果(返回给Client进程)

// 注:运行在Server进程的Binder线程池中;当Client进程发起远程请求时,远程请求会要求系统底层执行回调该方法

2.3 其中 new Proxy(mIBinder),需要创建代理对象,也需要实现服务接口

public class Proxy implements PersonManger {
    private IBinder mIBinder;
    public Proxy(IBinder mIBinder) {
        this.mIBinder =mIBinder;
    }

    @Override
    public void addPerson(Person mPerson) {
        Parcel data = Parcel.obtain();
        Parcel replay = Parcel.obtain();

        try {
            data.writeInterfaceToken(DESCRIPTOR);
            if (mPerson != null) {
                data.writeInt(1);
                mPerson.writeToParcel(data, 0);
            } else {
                data.writeInt(0);
            }
            mIBinder.transact(BinderObj.TRANSAVTION_addPerson, data, replay, 0);
            replay.readException();
        } catch (RemoteException e){
            e.printStackTrace();
        } finally {
            replay.recycle();
            data.recycle();
        }
    }

    @Override
    public List<Person> getPersonList() {
        Parcel data = Parcel.obtain();
        Parcel replay = Parcel.obtain();
        List<Person> result = null;
        try {
            data.writeInterfaceToken(DESCRIPTOR);
            mIBinder.transact(BinderObj.TRANSAVTION_getPerson, data, replay, 0);
            replay.readException();
            result = replay.createTypedArrayList(Person.CREATOR);
        }catch (RemoteException e){
            e.printStackTrace();
        } finally{
            replay.recycle();
            data.recycle();
        }
        return result;
    }

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

这里的代理对象实质就是client最终拿到的代理服务,通过这个就可以和Server进行通信了,首先通过Parcel将数据序列化,然后调用 remote.transact()将方法code,和data传输过去,对应的会回调在在Server中的onTransact()中

2.4 创建服务进程  onBind方法返回mStub对象,也就是Server中的Binder实体对象

public class ServerSevice extends Service {
    private static final String TAG = "ServerSevice";
    private List<Person> mPeople = new ArrayList<>();


    @Override
    public void onCreate() {
        mPeople.add(new Person());
        super.onCreate();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mStub;
    }
    private BinderObj mStub = new BinderObj() {
        @Override
        public void addPerson(Person mPerson) {
            if (mPerson==null){
                mPerson = new Person();
                Log.e(TAG,"null obj");
            }
            mPeople.add(mPerson);
            Log.e(TAG,mPeople.size()+"");
        }

        @Override
        public List<Person> getPersonList() {
            return mPeople;
        }
    };
}

2.5 最后,我们在客户端进程,bindService传入一个ServiceConnection对象,在与服务端建立连接时,通过我们定义好的BinderObj的asInterface方法返回一个代理对象,再调用方法进行交互

public class MainActivity extends AppCompatActivity {
    private boolean isConnect = false;
    private static final String TAG = "MainActivity";
    private PersonManger personManger;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        start();
        findViewById(R.id.textView).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (personManger==null){
                    Log.e(TAG,"connect error");
                    return;
                }
                personManger.addPerson(new Person());
                Log.e(TAG,personManger.getPersonList().size()+"");
            }
        });
    }

    private void start() {
        Intent intent = new Intent(this, ServerSevice.class);
        bindService(intent,mServiceConnection,Context.BIND_AUTO_CREATE);
    }
    private ServiceConnection mServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Log.e(TAG,"connect success");
            isConnect = true;
            personManger = BinderObj.asInterface(service);
            List<Person> personList = personManger.getPersonList();
            Log.e(TAG,personList.size()+"");
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG,"connect failed");
            isConnect = false;
        }
    };
}
  • 最后,客户端与服务端交互的流程

原理图

流程图

 

 

为什么Binder机制可以只是拷贝一次

Binder IPC 是基于内存映射(mmap)来实现的,但是 mmap() 通常是用在有物理介质的文件系统上的。

比如进程中的用户区域是不能直接和物理设备打交道的,如果想要把磁盘上的数据读取到进程的用户区域,需要两次拷贝(磁盘-->内核空间-->用户空间);通常在这种场景下 mmap() 就能发挥作用,通过在物理介质和用户空间之间建立映射,减少数据的拷贝次数,用内存读写取代I/O读写,提高文件读取效率。

而 Binder 并不存在物理介质,因此 Binder 驱动使用 mmap() 并不是为了在物理介质和用户空间之间建立映射,而是用来在内核空间创建数据接收的缓存空间。

一次完整的 Binder IPC 通信过程通常是这样:

首先 Binder 驱动在内核空间创建一个数据接收缓存区; 接着在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系; 发送方进程通过系统调用 copyfromuser() 将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。 如下图:

在这里插入图片描述


 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值