Framework笔记 | Android Framework用到了哪些IPC方式,分别在哪里用到

简介: Framework笔记 | Android Framework用到了哪些IPC方式,分别在哪里用到
  • 是否了解Linux常用的跨进程通信方式

android很多底层实现,
都依赖于Linux的操作系统调用;

  • 是否研究过Android Framework并了解一些实现原理
  • 是否了解Framework各组件之间的通信原理

很多组件基本都是要跨进程的,
跨进程通讯并不全是用Binder机制;

主要关注三个层面

  • 列举用到哪些IPC方式
  • 各个IPC方式的特点
  • Framework中是怎么用到的

Android中主要用到的Linux IPC方式

  • 管道
  • Socket
  • 共享内存
  • 信号




管道通信

  • 半双工的,单向的

管道的描述符数据只能往一个方向流,要么读要么写,
如果需要既能读又能写,则需要给管道有两个描述符
不过Linux给了我们一个APIpipe(fds)
这个API可以生成一对描述符
一个用来写一个用来读;

  • 一般无名管道是在父子进程之间使用的;

有名管道只要两个进程都知道这个管道的名字就可以通信了;

看一个例子

  • 通过pipe调用,生成管道的一对描述符;

**`fd[1]是用来写的;
fd[0]是用来读的;`**
通过fork()调用创建一个子进程;
子进程会继承这对描述符;

  • 现在我们要父进程往子进程里面写东西,

**首先,把子进程写描述符关闭,把子进程写描述符关闭
接着,父进程往写描述符里边写一个字符串
然后,子进程就可以从读描述符里边把这个字符串读出来;**

if(pid == 0){
    
    close(fd[1]);//把子进程写描述符关闭
    //子进程就可以从读描述符里边把这个字符串给读出来
    read(fd[0], buf, SIZE);


}else if(pid > 0){

    close(fd[0]);//把子进程写描述符关闭
    write(fd[1], "Hello", 5);//父进程往写描述符里边写一个字符串

}

**概念图如下,
我们可以看到数据流的方向是
父进程写描述符fd[1]--管道--子进程读描述符fd[0]
即,我们刚刚所说的半双工设计**:

Framework中哪儿用到了管道

  • Android 4.4中的MQ机制中的重要元素Looper,用到了管道

(更高的版本如Android 6.0用的就不是管道了):

  • 代码大概实现:

**前四行是为管道配置一对读写描述符
后半部分是注册一个监听事件
监听读描述符的读事件,即eventItem.data.fd = mWakeReadPipeFd;
这个时候如果有另一个线程拿到写描述符并往里面写东西的话,
读端就能收到通知了;**

相关阅读

epoll机制有一套函数,共三个,如下

创建epoll句柄:
1. int epfd =epoll_create(intsize);
创建一个epoll的句柄,size用来告诉内核这个监听的数目一共有多大。

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)
将被监听的描述符(对应例程中mWakeReadPipeFd
添加epoll句柄(对应例程中mEpollFd
或从epool句柄中删除或者对监听事件进行修改
(添加、删除和修改通过op位参数进行控制)
3. int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout)
**注意最后一句话,
该函数返回需要处理的事件数目,即几个事件被触发了,
第二个参数events列表用来接收存入触发的事件;**

接着看epoll是怎么监听读端事件的
  • 通过epoll_wait得到触发的事件列表及其数量;
  • for循环中遍历触发事件列表

遍历到事件的fd是刚刚设置的读描述符的(mWakeReadPipeFd),
及其事件是刚刚设定的读事件的(EPOLLIN),
则调用awoken(),把管道中的东西读出来,
管道满了就写不进去了,所以二话不说先读出来;

  • 不管管道里面写了什么东西,

只要写了东西,这个线程
就能被唤醒,就能去处理消息;

  • 当别的线程 要往这个Looper线程里面写东西的时候,

就通过wake()函数往管道里边写东西:

小结

**管道使用起来还是比较方便的,
它可以跟epoll相结合监听读写事件;

管道在进程自身中可以用,
跨进程也可以用;

在数据量不怎么大的跨进程通信的时候还是比较有用的;**




Socket通信

  • 这里说的不是网络上的socket,而是本地的;
  • 全双工,既可读又可写;
  • 可以用在两个无亲缘关系的进程之间的通信
  • socket在创建的时候需要指定一个路径,

只要把路径公开给别的进程,
别的进程就可以过来通信;

Framework中哪里用到

  • 在Zygote模块,

通过socket接收请求,然后启动应用进程;

  • main函数是Zygote的logo函数,

registerZygoteSocket()创建了一个本地的Socket,
socketName通过argv接收Socket的名字,
接着进入runSelectLoop(),一个循环,
检测这个socket有没有新过来的连接或者是数据;

我们看runSelectLoop()
  • 这里是一个循环,其中,

poll()用来监测有没有我们关注的事件发生,
如果有的话,可能会有两种情况,
第一种,是可能会有新的连接
第二种,就是有新的数据发过来,
这时候可以调用runOnce()来处理数据(先从Socket中把参数出来,
根据参数去执行响应的指令,主要是创建应用进程,
应用进程启动之后,通过Socket把pid给对方)

所以我们可以看到Socket其实很方便,
它即可以读又可以写;




共享内存

  • **很快,不需要多次拷贝;

拿到一个文件描述符(文件引用句柄),即把它映射到两个进程的内存空间,
这样,一个进程往里边写,另一个进程就能读到,运行速度非常快;

相对的,管道和Socket传输的数据量都不能太大,
如果太大的话性能会很糟,因为里边涉及到至少两次拷贝;**

  • **进程之间不用存在亲缘关系;

只需要能拿到文件描述符就好了;
文件描述符可以跨进程传递;**

Android中哪里用到

  • Android中涉及到进程之间大数据量传输的主要就是图像相关的传输
  • 这里主要以MemoryFile为例,

这是Android的一个工具类,
封装了内存共享机制Ashmem,也就是匿名共享内存;

MemoryFile是android在最开始就引入的一套框架,其内部实际上是封装了android特有的内存共享机制Ashmem匿名共享内存,简单来说,Ashmem在Android内核中是被注册成一个特殊的字符设备,Ashmem驱动通过在内核的一个自定义slab缓冲区中初始化一段内存区域,然后通过mmap把申请的内存映射到用户的进程空间中(通过tmpfs),这样子就可以在用户进程中使用这里申请的内存了。

参考文章

  • MemoryFile的实现,

首先是调用native_open方法,
这个方法在native层其实是
通过下面这个方法首先创建了一块匿名共享内存:native_open方法会返回一个描述符(句柄);

  • 接下来调用native_mmap函数,

这个函数在native层调用下面这个方法把描述符mFD映射到当前进程的内存空间,
内存空间的地址则返回过来,即例程中的mAddress;

  • 下面是MemoryFile的读和写
  • **读函数就是把数据共享内存 应用层的buff中,

SetByteArrayRegion()就是把nativebuff数据拷到java数据流的;**

  • **写函数则与读函数相反,

就是把数据应用层的buff拷到共享内存
GetByteArrayRegion()就是把java数据流中的数据拷到nativebuff的;**




信号

  • 单向的,只负责发出去,不接受回复的,

怎么处理,处理没有,处理结果怎么样都不管,是别人的事

  • 只能带个信号,不能带别的参数
  • 知道进程pid就能发信号,

可以一次给一群进程发信号

  • 必须是root权限才能发信号,

或者本进程跟另一进程的Userid相同,
本进程才能发信号;

Android中哪里用到

例1

  • 有时候要kill应用进程,

就会调用Proces的killProces函数,
这个函数中其实就是给进程发送了一个SIGNAL_KILL信号,
pid参数位就是要杀掉的进程pid;
当然不是想杀就能杀,同样这里是有权限控制的,
比如说本进程跟另一进程的Userid相同,
本进程才能发信号,杀掉另一个进程;

《开发艺术探索》中有一段类似的描述
  • **虽然我们的应用进程都是从Zygote那fork出来的,

UID都是默认和Zygote相同的,
但是进程启动之后,
就会马上重新设置自己的UID的,
所以基于任意进程是不可以随便给别的进程发信号的;**

zygote翻译成中文是受精卵的意思,名字比较奇怪、但是很有意思,
zygote在android中主要有 两个作用
建立运行时环境并启动虚拟机,为应用程序创建DVM进程。
执行com.android.internal.os.ZygoteInit的main函数,
从而fork SystemService。
类似参考文章
例2

  • 以上这个函数是Zygote用来关注信号的;

启动子进程之后,它需要关注子进程退出了没有,
如果子进程退出了,Zygote就要及时把子进程的资源给回收掉;




相关文章
|
3月前
|
Linux 编译器 Android开发
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
在Linux环境下,本文指导如何交叉编译x265的so库以适应Android。首先,需安装cmake和下载android-ndk-r21e。接着,下载x265源码,修改crosscompile.cmake的编译器设置。配置x265源码,使用指定的NDK路径,并在配置界面修改相关选项。随后,修改编译规则,编译并安装x265,调整pc描述文件并更新PKG_CONFIG_PATH。最后,修改FFmpeg配置脚本启用x265支持,编译安装FFmpeg,将生成的so文件导入Android工程,调整gradle配置以确保顺利运行。
154 1
FFmpeg开发笔记(九)Linux交叉编译Android的x265库
|
3月前
|
Unix Linux Shell
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
在Linux环境下交叉编译Android所需的FFmpeg so库,首先下载`android-ndk-r21e`,然后解压。接着,上传FFmpeg及相关库(如x264、freetype、lame)源码,修改相关sh文件,将`SYSTEM=windows-x86_64`改为`SYSTEM=linux-x86_64`并删除回车符。对x264的configure文件进行修改,然后编译x264。同样编译其他第三方库。设置环境变量`PKG_CONFIG_PATH`,最后在FFmpeg源码目录执行配置、编译和安装命令,生成的so文件复制到App工程指定目录。
288 9
FFmpeg开发笔记(八)Linux交叉编译Android的FFmpeg库
|
2天前
|
JavaScript 前端开发 Java
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
IT寒冬使APP开发门槛提升,安卓程序员需转型。选项包括:深化Android开发,跟进Google新技术如Kotlin、Jetpack、Flutter及Compose;研究Android底层框架,掌握AOSP;转型Java后端开发,学习Spring Boot等框架;拓展大前端技能,掌握JavaScript、Node.js、Vue.js及特定框架如微信小程序、HarmonyOS;或转向C/C++底层开发,通过音视频项目如FFmpeg积累经验。每条路径都有相应的书籍和技术栈推荐,助你顺利过渡。
13 3
FFmpeg开发笔记(四十七)寒冬下安卓程序员的几个技术转型发展方向
|
2月前
|
Java API Android开发
技术经验分享:Android源码笔记——Camera系统架构
技术经验分享:Android源码笔记——Camera系统架构
32 0
|
3月前
|
安全 Linux Android开发
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
该文介绍了如何在Linux服务器上交叉编译Android的FFmpeg库以支持HTTPS视频播放。首先,从GitHub下载openssl源码,解压后通过编译脚本`build_openssl.sh`生成64位静态库。接着,更新环境变量加载openssl,并编辑FFmpeg配置脚本`config_ffmpeg_openssl.sh`启用openssl支持。然后,编译安装FFmpeg。最后,将编译好的库文件导入App工程的相应目录,修改视频链接为HTTPS,App即可播放HTTPS在线视频。
73 3
FFmpeg开发笔记(十六)Linux交叉编译Android的OpenSSL库
|
3月前
|
Java 测试技术 开发工具
Android 笔记:AndroidTrain , Lint , build(1),只需一篇文章吃透Android多线程技术
Android 笔记:AndroidTrain , Lint , build(1),只需一篇文章吃透Android多线程技术
|
3月前
|
设计模式 缓存 前端开发
真的强!借助阿里技术博主分享的Android面试笔记,我拿到了字节跳动的offer
真的强!借助阿里技术博主分享的Android面试笔记,我拿到了字节跳动的offer
|
3月前
|
安全 Linux Android开发
Android最强保活黑科技的最强技术实现,2024年最新阿里资深Android开发带你搞懂Framework
Android最强保活黑科技的最强技术实现,2024年最新阿里资深Android开发带你搞懂Framework
Android最强保活黑科技的最强技术实现,2024年最新阿里资深Android开发带你搞懂Framework
|
3月前
|
存储 编解码 API
Android Media Framework(一)OpenMAX 框架简介
OpenMAX IL是Khronos Group为嵌入式和移动设备设计的低层级接口,用于统一调用音频、视频和图像编解码器,确保跨平台兼容性。它包括Core API(管理组件加载和方法调用)和Component API(组件实现,如源、接收器、编解码器等)。组件通过端口进行数据交互,客户端使用Core API加载和控制组件。Android引入OMX IL以支持不同芯片上的编解码器。组件状态包括Loaded、Idle、Executing和Invalid。组件架构涉及参数配置、命令处理和缓冲区管理,数据交换通过回调函数完成,端口持有预分配或组件自分配的缓冲区。
|
3月前
|
存储 Java API
Android系统 文件访问权限笔记
Android系统 文件访问权限笔记
350 1