Android7.0 Vold 进程工作机制分析之整体流程
来源:互联网 发布:电脑基本办公软件 编辑:程序博客网 时间:2024/06/05 17:52
一、Vold简介
Vold是Volume Daemon的缩写,负责管理和控制Android平台外部存储设备,包括SD插拨、挂载、卸载、格式化等。它是通过init进程解析init.rc脚本所启动的进程.它处于Native层.
二、基础架构
这里引用Gityuan博客的一张图。
SystermServer进程和Vold进程是通过Socket进行通信的,Vold进程和Kernel是通过Netlink 进行通信的,Netlink 是一种特殊的Socket。
相关介绍:Netlink是linux提供的用于内核和用户态进程之间的通信方式,也能用于用户空间的两个进程通信,通过这个机制,位于用户空间的进程,可接收来自Kernel的一些信息(例如Vold中用到的USB或SD的插拔消息),同时应用层也可通过Netlink向Kernel发送一些控制命令。
先大体的简单介绍一下流程:
1.由SystemServer进程发起挂载/卸载请求
运行在SystemServer进程的MountService通过NativeDaemonConnector给CommandListener发送请求,CommandListener再通知VolumeManager进行实际操作
2.由Kernel发起挂载/卸载请求
Kernel通过Netlink发送请求(传递uevent)给NetlinkManager,NetlinkManager通过内部的线程NetlinkHandler交给VolumeManager进行实际操作,然后VolumeManager通过CommandListener通知MountService
在分别仔细介绍着两个流程之前,了解下Vold进程的启动流程,先把握整体流程再细化。
三、Vold进程启动流程
Vold进程代码路径:system/vold/
主要类的路径(方便查阅)
system/vold/目录下
main.cpp————————————system/vold/main.cpp
NetlinkManager.cpp———————–system/vold/NetlinkManager.cpp
NetlinkHandler.cpp————————system/vold/NetlinkHandler.cpp
VoldCommand.cpp————————system/vold/VoldCommand.cpp
VolumeBase.cpp—————————system/vold/VolumeBase.cpp
VolumeManager.cpp———————–system/vold/VolumeManager.cpp
system/core/libsysutils/src/目录下
SocketListener.cpp————————–system/core/libsysutils/src/SocketListener.cpp
NetlinkListener.cpp————————–system/core/libsysutils/src/NetlinkListener.cpp
FrameworkListener.cpp——————–system/core/libsysutils/src/FrameworkListener.cpp
FrameworkCommand.cpp——————system/core/libsysutils/src//FrameworkCommand.cpp
system/core/include/sysutils/目录下
对应着system/core/libsysutils/src/目录的h文件
贴上我绘制的时序图(缩放浏览器可以放大查看或者在新标签页打开)
分步骤给大家详细介绍下:
1.main()
Vold进程代码位于system/vold/目录下,从main.cpp开始,后续的截图我只截取主要的代码
在main方法里,主要做以下几件事情
①初始化VolumeManager ,CommandListener ,NetlinkManager 三个类的实例
②给VolumeManager 和NetlinkManager 设置CommandListener 实例,用作后续监听两个Socket,用得是设计模式中的Command(命令)模式
③启动VolumeManager ,CommandListener ,NetlinkManager
④解析Vold的配置文件fstab
⑤做一次冷启动
- 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
- 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
第④步
如果vold.fstab解析无误,VolueManager将创建具体的Volume,若vold.fstab解析不存在或者打开失败,Vold将会读取Linux内核中的参数,此时如果参数中存在SDCARD(也就是SD的默认路径),VolumeManager则会创建AutoVolume,如果不存在这个默认路径那么就不会创建。
它的格式对应如下:
type———————–挂载命令
lable———————–标签
mount_point ————挂载点
part ———————–第几个分区
sysfs_path—————设备的sysfs paths
sysfs_path可以有多个 part指定分区个数,如果是auto没有分区
第⑤步
coldboot方法会调用do_coldboot方法,往/sys/block目录写入add\n事件。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
2.new CommandListener()
前面有讲过,CommandListener是用来监听Socket的,监听Vold与Framework层的进程通信。它的关系图如下:
它继承自FrameworkListener,FrameworkListener继承自SocketListener.
路径:
CommandListener.cpp———————–system/vold/CommandListener.cpp
这一步创建CommandListener的实例,则构造方法被调用
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
调用registerCmd方法,注册一些指令,重写的是父类的registerCmd方法
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
会把指令添加到mCommands 中,mCommands 是FrameworkCommandCollection的实例,在FrameworkListener.h文件中声明的
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
这里附上一张NetlinkManager家族的简单类图,帮助后续理解
3.vm->start()
启动VolumeManager
VolumeManager模块负责管理所有挂载的设备节点以及相关操作的实际执行,
路径:
VolumeManager.cpp———————–system/vold/VolumeManager.cpp
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
①卸载所有设备
②创建一个VolumeBase实例
③调用VolumeBase的create方法
这里附上一张VolumeManager家族的简单类图,帮助后续理解
看下第③个步骤
3.1 mInternalEmulated->create()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
向VolumeManager发送了VolumeCreated的消息,然后设置状态为已卸载.
这个notifyEvent的实现如下
3.2 notifyEvent
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
获取单例VolumeManager对象,然后获取到SocketListener对象调用sendBroadcast方法
sendBroadcast方法的实现如下
在safelist列表中添加SocketClient,然后调用sendMsg方法
- 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
- 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
SockClient
路径:
SockClient.cpp————————system/core/libsysutils/src/SockClient.cpp
调用sendMsg方法经过层层跳转,到sendDataLockedv方法中,往Socket中写入信息
3.3 sendDataLockedv
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
写入到Socket之后,SystemServer中的MountService会收到,后续再细讲.
4.nm->start()
这一步启动NetlinkManager
NetlinkManager
路径:
NetlinkManager.cpp———————–system/vold/NetlinkManager.cpp
NetlinkManager模块接收从Kernel通过Netlink机制发送过来的Uevent消息,解析转换成NetlinkEvent对象,再将此NetlinkEvent对象传递给VolumeManager处理。
start方法如下
- 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
- 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
①创建Socket,为PF_NETLINK类型
②设置Socket的SO_RCVBUFFORCE(接受缓存区)小
③设置Socket的SO_PASSCRED大小
④创建一个NetlinkHandler对象,并启动它
主要看第④步
4.1 mHandler->start()
构造函数传入了mSock,然后调用了NetlinkHandler的start方法
看一下它的实现
路径:
NetlinkHandler.cpp———————–system/vold/NetlinkHandler.cpp
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
NetlinkHandler继承自NetlinkListener,NetlinkListener继承自SocketListener,三者关系如下
4.2 startListener
会在父类SocketListener中实现,调用startListener方法
路径:
SocketListener.cpp————————–system/core/libsysutils/src/SocketListener.cpp
SocketListener
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
会开启一个线程,那么继续看threadStart方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
调用runListener
4.3 runListener
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
会调用onDataAvailable方法,改方法由子类NetlinkListener和FrameWorkListener实现,所以这里要分两条线4.4和4.5。
4.4 onDataAvailable
由子类FrameWorkListener实现这个方法
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
在onDataAvailable方法里会先读取Socket消息,然后分发命令
4.4.1 dispatchCommand
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
会调用FrameworkCommand 的runCommand方法,之前在CommandListener的构造方法里注册的这些指令,就是FrameWorkCommand类型,如下
FrameworkListener.cpp
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
CommandListener.cpp
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
这里以其中一个指令为VolumeCmd例,会进入到VolumeCmd的runCommand方法
4.4.2 CL.runCommand
CommandListener.cpp
- 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
- 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
会根据cmd的不同做相应的处理,在”cmd=mount”操作中,就有
- 1
- 1
4.4.3 vol->mount()
vol是VolumeBase的实例,VolumeBase的mount方法由具体的子类EmulatedVolume、PublicVolume、PrivateVolume等实现
执行操作之后会发送应答消息给MountService,这个后续再细讲。
这条线结束了。下面介绍另一条线。回到4.3 runListener,往下走到4.5 onDataAvailable
由子类NetlinkListener实现
4.5 onDataAvailable()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
NetlinkListener没有实现这个方法,由子类NetlinkHandler实现
4.5.1 onEvent
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
获取VolumeManager 单例,调用handleBlockEvent方法
4.5.2 vm->handleBlockEvent
- 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
- 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
根据NetlinkEvent 的不同Action值做相应处理,有add,change,remove三个值。在add里调用了disk->create()
4.5.3 disk->create()
路径:
disk.cpp———————–system/vold/disk.cpp
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
在这一步会调用notifyEvent方法通知SockListener.
- 1
- 2
- 3
- 1
- 2
- 3
到这一步骤,会发现又回到了3.2 notifyEvent步骤了,之后就跟着3.2继续走了,这里就不重复介绍了.
四、Vold进程总结
关于Vold的整体流程的讲完了,可以跟着我绘制的时序图跟着步骤走,来回多看几次,注意图文结合.
后面会针对
1.由SystemServer进程发起挂载/卸载请求
2.由Kernel发起挂载/卸载请求
这两种情况做更具体的分析,分析源码切记:先整体后局部,不然就没有头绪了,只见树木不见森林.
- Android7.0 Vold 进程工作机制分析之整体流程
- Android7.0 Vold 进程工作机制分析之整体流程
- Android7.0 Vold 进程工作机制分析之由Kernel发起挂载请求
- Android7.0 Vold 进程工作机制分析之由MountService发起挂载请求
- Vold工作机制分析
- android7.1的SnapdragonCamera之CameraActivity逻辑流程分析整体
- Vold工作流程分析学习
- Vold工作流程分析学习
- Vold工作流程分析学习
- Vold工作流程分析学习
- Vold工作流程分析学习
- Vold工作流程分析学习
- Android vold 工作流程分析
- Vold工作流程分析学习
- Vold工作流程分析學習
- Android7.0 Rild工作流程
- Android7.0 Rild工作流程
- Android7.0 Rild工作流程
- 文件目录
- Java实现短信验证
- 第一章 Java多线程技能
- python 基础(一)
- 解决:java.net.SocketException: sendto failed: ECONNRESET (Connection reset by peer)
- Android7.0 Vold 进程工作机制分析之整体流程
- 第十三周项目-验证算法(2)
- 安卓高德地图的使用
- C语言再学习 -- Xargs用法详解
- Mybatis Collection查询集合只出现一条数据
- 排序算法总结
- 使用Svox实现中文转语音TextToSpeech(TTS)
- Linux的五个查找命令
- opencv常用输入输出