基于Android 6.0的源码,剖析存储架构的设计
一、概述
本文讲述Android存储系统的架构与设计,涉及到最为核心的便是MountService和Vold这两个模块以及之间的交互。上一篇文章Android存储系统之源码篇从源码角度介绍相关模块的创建与启动过程,那么本文主要从全局角度把握和剖析Android的存储系统。
MountService:Android Binder服务端,运行在system_server进程,用于跟Vold进行消息通信,比如MountService
向Vold
发送挂载SD卡的命令,或者接收到来自Vold
的外设热插拔事件。MountService作为Binder服务端,那么相应的Binder客户端便是StorageManager,通过binder IPC与MountService交互。
Vold:全称为Volume Daemon,用于管理外部存储设备的Native daemon进程,这是一个非常重要的守护进程,主要由NetlinkManager,VolumeManager,CommandListener这3部分组成。
1.1 模块架构
从模块地角度划分Android整个存储架构:
图解:
- Linux Kernel:通过
uevent
向Vold的NetlinkManager发送Uevent事件; - NetlinkManager:接收来自Kernel的
Uevent
事件,再转发给VolumeManager; - VolumeManager:接收来自NetlinkManager的事件,再转发给CommandListener进行处理;
- CommandListener:接收来自VolumeManager的事件,通过
socket
通信方式发送给MountService; - MountService:接收来自CommandListener的事件。
涉及主要的问题:
- Framework层主要看
MountService.java
和NativeDaemonConnector.java
; - Native层主要看
NetlinkManager.cpp
,NetlinkHandler.cpp
,VolumeManager.cpp
,CommandListener.cpp
1.2 进程架构
(1)先看看Java framework层的线程:
1 2 3 4 5 6 |
root@gityuan:/ # ps -t | grep 1212 system 1212 557 2334024 160340 SyS_epoll_ 7faedddbe4 S system_server system 2662 1212 2334024 160340 SyS_epoll_ 7faedddbe4 S MountService system 2663 1212 2334024 160340 unix_strea 7faedde73c S VoldConnector system 2664 1212 2334024 160340 unix_strea 7faedde73c S CryptdConnector ... |
MountService运行在system_server进程,这里查询的便是system_server进程的所有子线程,system_server进程承载整个framework所有核心服务,子线程数有很多,这里只列举与MountService模块相关的子线程。
(2)再看看Native层的线程:
1 2 3 4 5 6 7 |
root@gityuan:/ # ps -t | grep " 387 " USER PID PPID VSIZE RSS WCHAN PC NAME root 387 1 13572 2912 hrtimer_na 7fa34755d4 S /system/bin/vold root 397 387 13572 2912 poll_sched 7fa3474d1c S vold root 399 387 13572 2912 poll_sched 7fa3474d1c S vold root 400 387 13572 2912 poll_sched 7fa3474d1c S vold media_rw 2702 387 7140 2036 inotify_re 7f84b1d6ac S /system/bin/sdcard |
Vold作为native守护进程,进程名为”/system/bin/vold”,pid=387,通过ps -t
可查询到该进程下所有的子进程/线程。
小技巧:有读者可能会好奇,为什么/system/bin/sdcard
是子进程,而非子线程呢?要回答这个问题,有两个方法,其一就是直接看撸源码,会发现这是通过fork
方式创建的,而其他子线程都是通过pthread_create
方式创建的。当然其实还有个更快捷的小技巧,就是直接看上图中的第4列,这一列的含义是VSIZE
,代表的是进程虚拟地址空间大小,是否共享地址空间,这是进程与线程最大的区别,再来看看/sdcard的VSIZE大小跟父进程不一样,基本可以确实/sdcard是子进程。
(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: 同一个模块可以运行在各个不同的进程/线程, 同一个进程可以运行不同模块的代码,所以从进程角度和模块角度划分看到的有所不同的.
1.3 类关系图
上图中4个蓝色块便是前面谈到的核心模块。
二、 通信架构
Android存储系统中涉及各个进程间通信,这个架构采用的socket,并没有采用Android binder IPC机制。这样的架构代码大量更少,整体架构逻辑也相对简单,在介绍通信过程前,先来看看MountService对象的实例化过程,那么也就基本明白进程架构中system_sever进程为了MountService服务而单独创建与共享使用到线程情况。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
public MountService(Context context) { sSelf = this; mContext = context; //FgThread线程名为“"android.fg",创建IMountServiceListener回调方法 mCallbacks = new Callbacks(FgThread.get().getLooper()); //获取PKMS的Client端对象 mPms = (PackageManagerService) ServiceManager.getService("package"); //创建“MountService”线程 HandlerThread hthread = new HandlerThread(TAG)β述Android存储系统的架构与设计,涉及到最为核心的便是MountService和Vold这两个模块以及之间的交互。上一篇文章Android存储系统之源码篇从源码角度介绍相关模块的创建与启动过程,那么本文主要从全局角度把握和剖析Android的存储系统。
MountService:Android Binder服务端,运行在system_server进程,用于跟Vold进行消息通信,比如 Vold:全称为Volume Daemon,用于管理外部存储设备的Native daemon进程,这是一个非常重要的守护进程,主要由NetlinkManager,VolumeManager,CommandListener这3部分组成。 1.1 模块架构从模块地角度划分Android整个存储架构: 图解:
涉及主要的问题:
1.2 进程架构(1)先看看Java framework层的线程:
MountService运行在system_server进程,这里查询的便是system_server进程的所有子线程,system_server进程承载整个framework所有核心服务,子线程数有很多,这里只列举与MountService模块相关的子线程。 (2)再看看Native层的线程:
Vold作为native守护进程,进程名为”/system/bin/vold”,pid=387,通过 小技巧:有读者可能会好奇,为什么 (3) 从进程/线程视角来看Android存储架构:
注:图中红色字代表的进程/线程名,vold进程通过pthread_create的方式创建的3个子线程名都为vold,图中只是为了便于区别才标注为vold1, vold2, vold3,其实名称都为vold。 Android还可划分为内核空间(Kernel Space)和用户空间(User space),从上图可看出,Android存储系统在User space总共采用9个进程/线程的架构模型。当然,除了这9个进/线程,另外还会在handler消息处理过程中使用到system_server的两个子线程: Tips: 同一个模块可以运行在各个不同的进程/线程, 同一个进程可以运行不同模块的代码,所以从进程角度和模块角度划分看到的有所不同的. 1.3 类关系图上图中4个蓝色块便是前面谈到的核心模块。 二、 通信架构Android存储系统中涉及各个进程间通信,这个架构采用的socket,并没有采用Android binder IPC机制。这样的架构代码大量更少,整体架构逻辑也相对简单,在介绍通信过程前,先来看看MountService对象的实例化过程,那么也就基本明白进程架构中system_sever进程为了MountService服务而单独创建与共享使用到线程情况。
|