Android7.0 Vold 进程工作机制分析之由Kernel发起挂载请求
一、MountService简介
MountService是一个系统服务,负责与Vold进程通信的,运行在SystemServer进程,当收到Vold的挂载消息后,会通过广播的方式通知上层应用.
它是在SystemServer的startOtherServices方法里启动的
SystemServer路径——————/frameworks/base/services/java/com/android/server/SystemServer.java
private void startOtherServices() {
......
//如果不为低级工厂测试
if (mFactoryTestMode != FactoryTest.FACTORY_TEST_LOW_LEVEL) {
if (!disableStorage &&!"0".equals(SystemProperties.get("system_init.startmountservice"))) {
try {
//启动MountService
mSystemServiceManager.startService(MOUNT_SERVICE_CLASS);
mountService = IMountService.Stub.asInterface(ServiceManager.getService("mount"));
} catch (Throwable e) {
reportWtf("starting Mount Service", e);
}
}
}
......
}
这里并不打算详细介绍MountService的启动过程,只需关注它的构造方法即可(在启动时会调用构造方法)
MountService路径——————/frameworks/base/services/core/java/com/android/server/MountService.java
class MountService extends IMountService.Stub implements INativeDaemonConnectorCallbacks, Watchdog.Monitor {
......
public MountService(Context context) {
......
//创建并启动一个带消息循环的MountService工作线程
HandlerThread hthread = new HandlerThread(TAG);
hthread.start();
//为MountService工作线程创建一个Handler
mHandler = new MountServiceHandler(hthread.getLooper());
......
/*
NativeDaemonConnector用于Socket通信,第二个参数“vold”表示将和Vold通信,也就是
和CL模块中的那个socket建立通信连接。第一个参数为INativeDaemonConnectorCallbacks
接口。它提供两个回调函数:
onDaemonConnected:当NativeDaemonConnector连接上Vold后回调。
onEvent:当NativeDaemonConnector收到来自Vold的数据后回调。
*/
mConnector = new NativeDaemonConnector(this, "vold", MAX_CONTAINERS * 2, VOLD_TAG, 25,
null);
//创建线程名为"VoldConnector"的线程,用于跟vold通信
mConnectorThread = new Thread(mConnector, VOLD_TAG);
......
}
主要做了以下几件事
①创建并启动一个带消息循环的MountService工作线程 HandlerThread
②为MountService工作线程创建一个Handler
③创建线程名为”VoldConnector”的线程,用于跟vold通信
在MountService的start方法启动这个线程
private void start() {
mConnectorThread.start();
}
这个VoldConnector线程在run方法里会调用一个方法listenToSocket,监听Vold进程发过来的Socket消息
NativeDaemonConnector路径——/frameworks/base/services/core/java/com/android/server/NativeDaemonConnector.java
final class NativeDaemonConnector implements Runnable, Handler.Callback, Watchdog.Monitor {
......
@Override
public void run() {
mCallbackHandler = new Handler(mLooper, this);
while (true) {
try {
//监听Vold进程发过来的socket消息
listenToSocket();
} catch (Exception e) {
loge("Error in NativeDaemonConnector: " + e);
SystemClock.sleep(5000);
}
}
}
......
}
在listenToSocket方法里会建立Socket连接,把接收的消息解析成NativeDaemonEvent事件,通过mCallbackHandler处理这个事件
private void listenToSocket() throws IOException {
LocalSocket socket = null;
try {
socket = new LocalSocket();
LocalSocketAddress address = determineSocketAddress();
//建立与"/dev/socket/vold"的socket连接
socket.connect(address);
......
try {
//解析成 NativeDaemonEvent事件
final NativeDaemonEvent event = NativeDaemonEvent.parseRawEvent(rawEvent, fdList);
//当响应码区间为[600,700),则发送消息交由mCallbackHandler处理
Message msg = mCallbackHandler.obtainMessage( event.getCode(), uptimeMillisInt(), 0, event.getRawEvent());
......
}
}
关于MountService的简介先到这里,下面分析Kernel发起挂载请求的流程.
二、Kernel发起挂载请求的流程
上一篇文章Android7.0 Vold 进程工作机制分析之整体流程已经讲了,Kernel是通过Netlink 进行通信的,Netlink 是一种特殊的Socket。
以下是上一篇文章的Vold 进程启动时序图(缩放浏览器可以放大查看或者在新标签页打开)
这里以SD卡插入,Kernel挂载请求为例,流程从NetlinkListener的onDataAvailable开始
1.NetlinkListener::onDataAvailable
bool NetlinkListener::onDataAvailable(SocketClient *cli)
{
int socket = cli->getSocket();
ssize_t count;
uid_t uid =