当前位置:首页 » 安卓系统 » android跨进程

android跨进程

发布时间: 2023-09-25 16:00:57

⑴ Android跨进程传递大数据

最近要从 Service 端给 Client 端传递图片数据,之前的数据都是通过 aidl 传递:
创建 Parcelable 文件
ImageData.java

test.aidl

运行报错:

这里导致 DeadObjectException 的原因主要是 binder 创建的 buffer 被占满了:

传输中如果数据大于 free_buffers ,则会抛出 DeadObjectException

socke 传输不受大小限制,但实现比较复杂

通过文件传输比较简单,但效率差,而且高版本会受到Android系统权限限制

将较大数据切割成较小的数据传输,此方法是兼顾效率,复杂度较好的方案

定义数据体:

切割数据方法:

将ImageData按顺序构建发送:

client接收:

binder 本身也是利用 mmap ,可以利用实现 mmap 的框架,比如 MMKV

如果传输的数据是 Bitmap ,还可以用 Bundle 的 putBinder 方案
定义 binder :

发送

接收:

⑵ Android 跨进程通信--Binder篇

话说Binder 其实是由George Hoffman 老哥,在1991年Be公司启动了一个“openBinder”的项目,该项目的宗旨是研究一个高效的信号传递工具,允许多个软件相互合作,构成一个软件系统。在BE被parmSource收购以后,openBinder由hackborn继续开发。在Hackborn加入google之后,他继续开发出了Android Binder。

而Android系统是基于Linux内核实现的,Linux已经提供了多种进程间通信机制,比如:管道、消息队列、共享内存和套接字(Socket)等等。

讲它们优缺点前先补充说明:
“进程隔离”--这个技术是为了避免进程A写入进程B的情况发生。 进程的隔离实现,使用了虚拟地址空间进程A的虚拟地址和进程B的虚拟地址不同,这样就防止进程A将数据信息写入进程B。进程隔离的安全性通过禁止进程间内存的访问可以方便实现。相比之下,一些不安全的操作系统DOS能够允许任何进程对其他进程的内存进行写操作。

“虚拟内存”-- 是计算机系统内存管理的一种技术。它使得应用程序认为它拥有连续可用的内存(一个连续完整的地址空间),而实际上,它通常是被分隔成多个物理内存碎片,还有部分暂时存储在外部磁盘存储器上,在需要时进行数据交换。与没有使用虚拟内存技术的系统相比,使用这种技术的系统使得大型程序的编写变得更容易,对真正的物理内存的使用也更有效率。

注意: 虚拟内存 不只是“用磁盘空间来扩展物理内存”的意思——这只是扩充内存级别以使其包含硬盘驱动器而已。把内存扩展到磁盘只是使用虚拟内存技术的一个结果,它的作用也可以通过覆盖或者把处于不活动状态的程序以及它们的数据全部交换到磁盘上等方式来实现。对虚拟内存的定义是基于对地址空间的重定义的,即把地址空间定义为“连续的虚拟内存地址”,以借此“欺骗”程序,使它们以为自己正在使用一大块的“连续”地址。

⑶ 安卓IPC跨进程通讯:AIDL+Retrofit——AndLinker的初步使用

需要用到安卓跨进程通讯,明指IPC (进程间通信) 的时候,AndLinker是一款Android上的IPC (进程间通信) 库,结合了 AIDL 和 Retrofit 的诸多特性,且可以与 RxJava 和 RxJava2 的Call Adapters无缝结合使用。

个人简单理解就是:简化AIDL流程的一个第三方库。使用时斗昌需要先了解一下AIDL、retrofit。

以普通Java接口代替AIDL接口

像 Retrofit 一样生成远程服务接口的IPC实现

支持的Call Adapters:Call, RxJava  Observable, RxJava2  Observable & Flowable

支持远程服务回调机制

支持AIDL的所有数据类型

支持AIDL的所有数据定向tag:in,out,inout

支持AIDL的oneway关键字

在服务端以及客户端的项目根目录的build.gradle中添加jcenter()仓库

在App的build.gradle中添加如下依赖

AndLinker支持AIDL所有数据类型:

Java语言中的所有原始类型 (如:int,long,char,boolean,等等)

String

CharSequence

Parcelable

List (List中的所有元素必须是此列表中支持的数据类型)

Map (Map中的所有元素必须是此列表中支持的数据类型)

接口里的方法就是按需激销配求需创建。这里只举几个简单的示例。

⑷ Android跨进程通信-共享内存

还是先看共享内存的使用方法,我主要介绍两个函数:

通过 shmget() 函数申请共享内存,它的入参如下

通过 shmat() 函数将我们申请到的共享内存映射到自己的用户空间,映射成功会返回地址,有了这个地址,我们就可以随意的读写数据了,我们继续看一下这个函数的入参

共享内存的原理是在内存中单独开辟的一段内存空间,这段内存空间其实就是一个tempfs(临时虚拟文件),tempfs是VFS的一种文件系统,挂载在/dev/shm上,前面提到的管道pipefs也是VFS的一种文件系统。

由于共享的内存空间对使用和接收进程来讲,完全无感知,就像是在自己的内存上读写数据一样,所以也是 效率最高 的一种IPC方式。

上面提到的IPC的方式都是 在内核空间中开辟内存来存储数据 ,写数据时,需要将数据从用户空间拷贝到内核空间,读数据时,需要从内核空间拷贝到自己的用户空间,
共享内存就只需要一次拷贝 ,而且共享内存不是在内核开辟空间,所以可以 传输的数据量大

但是 共享内存最大的缺点就是没有并发的控制,我们一般通过信号量配合共享内存使用,进行同步和并发的控制

共享内存在Android系统中主要的使用场景是 用来传输大数据 ,并且 Android并没有直接使用Linux原生的共享内存方式,而是设计了Ashmem匿名共享内存

之前说到有名管道和匿名管道的区别在于有名管道可以在vfs目录树中查看到这个管道的文件,但是匿名管道不行, 所以匿名共享内存同样也是无法在vfs目录中查看到 的, Android之所以要设计匿名共享内存 ,我觉得主要是为了安全性的考虑吧。

我们来看看共享内存的一个使用场景,在Android中,如果我们想要将当前的界面显示出来,需要将当前界面的图元数据传递Surfaceflinger去做图层混合,图层混合之后的数据会直接送入帧缓存,送入帧缓存后,显卡就会直接取出帧缓存里的图元数据显示了。

那么我们如何将应用的Activity的图元数据传递给SurfaceFlinger呢?想要将图像数据这样比较大的数据跨进程传输,靠binder是不行的,所以这儿便用到匿名共享内存。

从谷歌官方提供的架构图可以看到,图元数据是通过BufferQueue传递到SurfaceFlinger去的,当我们想要绘制图像的时候, 需要从BufferQueue中申请一个Buffer,Buffer会调用Gralloc模块来分配共享内存 当作图元缓冲区存放我们的图元数据。

可以看到Android的匿名共享内存是通过 ashmem_create_region() 函数来申请共享内存的,它会在/dev/ashmem下创建一个虚拟文件,Linux原生共享内存是通过shmget()函数,并会在/dev/shm下创建虚拟文件。

匿名共享内存是通过 mmap() 函数将申请到的内存映射到自己的进程空间,而Linux是通过*shmat()函数。

虽然函数不一样,但是Android的匿名共享内存和Linux的共享内存在本质上是大同小异的。

要使用一块共享内存

⑸ Android之Binder通信篇

Binder跨进程通信的本质是依赖内核驱动将属于不同Binder进程的数据,从原始进程复制到目标进程,这样就完成了跨进程通信了。

Binder通过独特的内存映射机制,在跨进程通信时,可以做到一次拷贝,两个空间同时使用!如下图:

Binder跨进程通信是要传递数据的,既然有数据必然要占用内存空间,Android系统规定每一个进程都有一块Binder内存区,也就是图1中的 共享内存 ,系统最多只能给该区域分配4M的物理内存,由于申请这块内存是通过系统的mmap函数完成的,所以整个映射机制又被称为mmap机制
为了把这部分说明白,就再盗图一张,命名图2吧!

对于Binder驱动,通过 binder_procs 链表记录所有创建的 binder_proc 结构体,binder 驱动层的每一个 binder_proc 结构体都与用户空间的一个用于 binder 通信的进程一一对应,且每个进程有且只有一个 ProcessState 对象,这是通过单例模式来保证的。在每个进程中可以有很多个线程,每个线程对应一个 IPCThreadState 对象,IPCThreadState 对象也是单例模式,即一个线程对应一个 IPCThreadState 对象,在 Binder 驱动层也有与之相对应的结构,那就是 Binder_thread 结构体。在 binder_proc 结构体中通过成员变量 rb_root threads,来记录当前进程内所有的 binder_thread。

Binder 线程池:每个 Server 进程在启动时创建一个 binder 线程池,并向其中注册一个 Binder 线程;之后 Server 进程也可以向 binder 线程池注册新的线程,或者 Binder 驱动在探测到没有空闲 binder 线程时主动向 Server 进程注册新的的 binder 线程。对于一个 Server 进程有一个最大 Binder 线程数限制,默认为16个 binder 线程,例如 Android 的 system_server 进程就存在16个线程。对于所有 Client 端进程的 binder 请求都是交由 Server 端进程的 binder 线程来处理的。

热点内容
cf弹道脚本 发布:2025-01-26 15:36:40 浏览:54
我的世界花钱买的服务器 发布:2025-01-26 15:34:50 浏览:89
php环境部署 发布:2025-01-26 15:28:09 浏览:17
python实现svm 发布:2025-01-26 15:24:25 浏览:381
易语言写ip全局代理服务器 发布:2025-01-26 15:04:01 浏览:668
gm命令在哪个文件夹 发布:2025-01-26 15:03:12 浏览:307
javadate类 发布:2025-01-26 14:58:54 浏览:352
领航s1配置怎么样 发布:2025-01-26 09:58:10 浏览:763
公司局域网搭建服务器搭建 发布:2025-01-26 09:16:56 浏览:433
android裁剪圆形图片 发布:2025-01-26 09:05:56 浏览:411