正文
(3) 从进程/线程视角来看Android存储架构:
-
Java
层:采用
1个主线程
(system_server) +
3个子线程
(VoldConnector, MountService, CryptdConnector);
-
Native层:采用
1个主线程
(/system/bin/vold) +
3个子线程
(vold) +
1子进程
(/system/bin/sdcard);
注:图中红色字代表的进程/线程名,vold进程通过pthread_create的方式创建的3个子线程名都为vold,图中只是为了便于区别才标注为vold1, vold2, vold3,其实名称都为vold。
Android还可划分为内核空间(Kernel Space)和用户空间(User space),从上图可看出,Android存储系统在User space总共采用9个进程/线程的架构模型。当然,除了这9个进/线程,另外还会在handler消息处理过程中使用到system_server的两个子线程:
android.fg
和
android.io
。
Tips: 同一个模块可以运行在各个不同的进程/线程, 同一个进程可以运行不同模块的代码,所以从进程角度和模块角度划分看到的有所不同的.
为了阐述清楚存储系统的通信架构,主要分为以下4个过程:
-
MountService发送消息:MountService是如何从向vold守护进程通信;
-
MountService接收消息:MountService接收到vold发送过来的消息又是如何处理;
-
Kernel上报事件:当存储设备发生热插拔等事件,kernel是如何通知用户空间的vold;
-
不请自来的广播:对于事件往往都是MountService下发,然后再收到底层的回应,但对于有些广播却非如此,而是由底层直接触发,对于MountService来说却是“不请自来”的消息。
限于篇幅过长,本文先讲述前两个过程,下一篇文章再来说说后两个过程。
上图中4个蓝色块便是前面谈到的核心模块。
Android存储系统中涉及各个进程间通信,这个架构采用的socket,并没有采用Android binder IPC机制。这样的架构代码大量更少,整体架构逻辑也相对简单,在介绍通信过程前,先来看看MountService对象的实例化过程,那么也就基本明白进程架构中system_sever进程为了MountService服务而单独创建与共享使用到线程情况。
首先,MountService对象实例化的过程中完成是:
-
创建ICallbacks回调方法,FgThread线程名为"android.fg",此处用到的Looper便是线程"android.fg"中的Looper;
-
创建并启动线程名为"MountService"的handlerThread;
-
创建OBB操作的handler,IoThread线程名为"android.io",此处用到的的Looper便是线程"android.io"中的Looper;
-
创建NativeDaemonConnector对象
-
创建并启动线程名为"VoldConnector"的线程;
-
创建并启动线程名为"CryptdConnector"的线程;
-
注册监听用户添加、删除的广播;
从这里便可知道共创建了3个线程:
MountService
,
VoldConnector
,
CryptdConnector
,另外还会使用到系统进程中的两个线程
android.fg
和
android.io
. 这便是在文章开头进程架构图中Java framework层进程的创建情况.
system_server进程与vold守护进程间采用socket进行通信,这个通信过程是由MountService线程向vold线程发送消息。这里以执行mount调用为例:
public void mount(String volId) {
//【见小节2.1.2】