ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

Android Ashmem匿名共享内存,小白必看

2021-09-07 14:02:17  阅读:219  来源: 互联网

标签:return val Binder Ashmem FileDescriptor reply Android 共享内存


*/
private fun invokeMethod(name: String, obj: Any): Any? {
val method = obj.javaClass.getDeclaredMethod(name)
return method.invoke(obj)
}


MemoryFile 有两个构造方法,上面是一种,另一种是根据已有的 FileDescriptor 创建。 MemoryFile 创建时指定的大小并不是实际占用的物理内存大小,实际占用内存大小由写入的数据决定,但不能超过指定的大小。

3\. 将文件描述符传递到其他进程
-----------------

这里选择用 Binder 传递 ParcelFileDescriptor。 我们定义一个 Code,用于 C/S 两端通信确定事件:

/**

  • 两个进程在传递 FileDescriptor 时用到的 Code。
    */
    const val MY_TRANSACT_CODE = 920511

再在需要的地方 bindService:

// 创建服务进程
val intent = Intent(this, MyService::class.java)
bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)


bind 成功之后将 文件描述符 和 数据大小 序列化,然后通过 Binder 传递到 Service 进程:

private val serviceConnection = object: ServiceConnection {

override fun onServiceConnected(name: ComponentName?, binder: IBinder?) {
    if (binder == null) {
        return
    }

    // 创建 MemoryFile,并拿到 ParcelFileDescriptor
    val descriptor = createMemoryFile() ?: return

    // 传递 FileDescriptor 和 共享内存中数据的大小
    val sendData = Parcel.obtain()
    sendData.writeParcelable(descriptor, 0)
    sendData.writeInt(bytes.size)

    // 保存对方进程的返回值
    val reply = Parcel.obtain()

    // 开始跨进程传递
    binder.transact(MY_TRANSACT_CODE, sendData, reply, 0)

    // 读取 Binder 执行的结果
    val msg = reply.readString()
    Log.i("ZHP", "Binder 执行结果是:「$msg」")
}

override fun onServiceDisconnected(name: ComponentName?) {}

}


两个进程的文件描述符指向同一个文件结构体,文件结构体指向了一片内存共享区域(ASMA),使得两个文件描述符对应到同一片ASMA中。

4\. 在其他进程接收 FileDescriptor 并读取数据
--------------------------------

先定义一个 MyService 用于开启子进程:

class MyService : Service() {

private val binder by lazy { MyBinder() }

override fun onBind(intent: Intent) = binder

}


再实现具体的 MyBinder 类,主要包含3个步骤: 1. 从序列化数据中读取 FileDescriptor 和 共享内存中保存的数据大小; 2. 根据 FileDescriptor 创建 FileInputStream; 3. 读取共享内存中的数据。

/**

  • 这里不必使用 AIDL,继承 Binder 类 重写 onTransact 即可。
    */
    class MyBinder: Binder() {

    /**

    • 文件描述符 和 数据大小 通过 data 传入。
      */
      override fun onTransact(code: Int, data: Parcel, reply: Parcel?, flags: Int): Boolean {
      val parent = super.onTransact(code, data, reply, flags)
      if (code != MY_TRANSACT_CODE && code != 931114) {
      return parent
      }

      // 读取 ParcelFileDescriptor 并转为 FileDescriptor
      val pfd = data.readParcelable(javaClass.classLoader)
      if (pfd == null) {
      return parent
      }
      val descriptor = pfd.fileDescriptor

      // 读取共享内存中数据的大小
      val size = data.readInt()

      // 根据 FileDescriptor 创建 InputStream
      val input = FileInputStream(descriptor)

最后

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析

资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图

]

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析

[外链图片转存中…(img-T3zIVqpO-1630993762235)]

资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图

CodeChina开源项目:《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》

标签:return,val,Binder,Ashmem,FileDescriptor,reply,Android,共享内存
来源: https://blog.csdn.net/m0_61068325/article/details/120156431

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有