【Android源码 栏目提醒】:网学会员为需要Android源码 的朋友们搜集整理了Android磁盘管理-系统源码分析 - 电子设计相关资料,希望对各位网友有所帮助!
Android Vold架构 1. 总体架构 2. 流程概览 2.1 开启Vold 2.2 引导Uevent 2.3 处理事件 Vold - Volume Daemon存储类的守护进程作为
Android的一个本地服务负责处理诸如SD、USB等存储类设备的插拔等事件。
1. 总体架构 Vold服务由volumeManager统一管控它将具体任务分别分派给netlinkManager commandListener directVolume Volume去完成。
Vold服务向下通过socket机制与底层驱动交互向上通过JNI intent socket doCommand等机制与Java Framework交互。
2 流程概览 2.1 开启服务 初始化
Android系统时开启Vold本地服务 Vold在/dev/block下创建vold文件夹开启VolumeManager NetlinkManager CommandListener。
2.2 引导Uevent NetlinkManager负责监听底层Linux上报的uevent事件。
系统的SocketListner统一管理所有socket事件。
NetlinkListner负责解析socket事件。
最后由onEvent将vold事件交还给NetlinkManager处理。
2.3 处理Block和Switch事件 NetlinkManager调用VolumeManager中处理vold事件的类。
handleBlockEvent完成SD的挂载和卸载具体交由DirectVolume完成。
handleSwitchEvent完成由USB实现的U盘的连接。
两者最后都是通过setBroadcast将ResponsibleCode经过nativeDaemonConnector的socket监听机制最终上传到MountService作统一规划。
MountService里的onEvent得到解析后的事件完成两大任务 -gt 发送命令doCommand通过commandListener传递给volumeManager -gt 将事件信息广播给相关服务供上层应用使用。
Android磁盘管理-系统
源码分析1 本系列文章将会详细讲解
Android系统的磁盘管理部分可以通过这个突破口熟悉整个
Android的系统架构与实现原理。
Android磁盘管理总共涉及到四大部分
源码 1.Linux kernel
Android建立在Linux内核的基础上最底层的部分是由Linux kernel来负责的用于检测热插拔事件 2.VoldAndroid没有使用Linux平台下的udev来处理于是Google写了一个类似udev功能的vold充当了kernel与framework之间的桥梁 3.FrameworkAndroid的核心框架仅仅磁盘管理这部分负责操作vold给vold下发操作命令 4.UIAndroidd的系统应用与Framework进行交互用于挂载/卸载SD卡。
Android挂载SD卡流程如下 1.用户在“设置”页面的“SD卡和手机内存”中点击“挂载” 2.UI从Framework获取操作磁盘的函数向Framework注册才能使用的函数然后调用挂载的处理函数 3.该处理函数通过广播机制发送挂载命令“volume mount sdcard”vold接受命令并挂载SD卡后用广播通知Framework 4.Framework收到挂载SD卡的回复通知UI的处理结果 5.界面显示挂载成功/挂载失败。
从这里可以看出
Android的磁盘管理涉及到整个系统框架这是
Android系统很重要的一个子系统通过磁盘管理的子系统来熟悉
Android系 统架构能够了解到
Android的多方面知识。
从SD卡的挂载流程可以看出
Android系统大量地使用IPC从而做到了模块独立的效果。
从磁盘管 理的那四大部分来看四个部分之间的相互联系均是使用socket进行通信没有使用到传统的API调用整个系统就显得非常的独立。
源码的位置 Vold:system/vold Framework: frameworks/base/services/java/com/
android/server UI:
android-2.2r2/packages/apps/Settings/src/com/
android/settings/deviceinfo/
Android磁盘管理-之vold
源码分析2 Vold是
Android系统处理磁盘的核心部分取代了原来Linux系统中的udev主要用来处理
Android系统的热插拔存储设备。
在
Android2.2以后的系统中vold
源码已经移到了system目录下vold目录包含以下
源码 ├——
Android.mk ├—— Asec.h ├—— CleanSpec.mk ├—— CommandListener.cpp ├—— CommandListener.h ├—— Devmapper.cpp ├—— Devmapper.h ├—— DirectVolume.cpp ├—— DirectVolume.h ├—— Fat.cpp ├—— Fat.h ├—— hash.h ├—— logwrapper.c ├—— Loop.cpp ├—— Loop.h ├—— main.cpp ├—— NetlinkHandler.cpp ├—— NetlinkHandler.h ├—— NetlinkManager.cpp ├—— NetlinkManager.h ├—— Process.cpp ├—— Process.h ├—— ResponseCode.cpp ├—— ResponseCode.h ├—— vdc.c ├—— VoldCommand.cpp ├—— VoldCommand.h ├—— Volume.cpp ├—— Volume.h ├—— VolumeManager.cpp ├—— VolumeManager.h ├—— Xwarp.cpp └—— Xwarp.h 先简要说明一下类的继承关系vold中比较重要的有以下几个类 三大管理类VolumeManagerCommandListenerNetlinkManager 其他处理类VolumeDirectVolumeNetlinkHandlerFatResponseCode 其他相关的类NetlinkListenerSocketListener 1.VolumeManager管理Volume类 2.DirectVolume类继承于Volume类保存着磁盘信息与操作函数 3.NetlinkManager类负责与内核uevent事件通信期间使用到了NetlinkListener和SocketListener类的函数 4.Fat是格式化sd卡的函数 5.ResponseCode保存着vold向framework反馈的值。
本文讲解main.cpp文件的源代码 cpp view plaincopy 1. int main 2. / 3. 以下三个类声明三个指针对象 4. VolumeManager :管理所有存储设备volume对象 5. CommandListener :监听Framework下发的消息并分析命令调用响应的操作函数 6. NetlinkManager :监听Linux内核的热插拔事件uevent事件 7. / 8. VolumeManager vm 9. CommandListener cl 10. NetlinkManager nm 11. 12. SLOGIquotVold 2.1 the revenge firing upquot 13. / 14. 在Linux系统如scsi硬盘U盘的设备节点默认生成在/dev/目录下
Android把这些设备 15. 节点改到了/dev/block/目录下。
但随着热插拔事件的产生设备节点如sdasdb经常变换 16. 对于vold来说可能有点麻烦所以在/dev/block/下新建了一个名为vold的目录存放sda 17. sdb对应的设备节点形如quot8:0quot。
18. eg:sda 的主次设备号分别为80于是vold就会在vold目录下创建名为quot8:0quot的节点基于主次设备号 19. 命名便于程序操作增加了灵活性。
20. / 21. mkdirquot/dev/block/voldquot 0755 22. 23. / 24. 实例化vm对象VolumeManager类调用自身的Instance函数new了一个对象给vm。
25.
源码 26. VolumeManager VolumeManager::Instance 27. if sInstance 28. sInstance new VolumeManager 29. return sInstance 30. 31. / 32. if vm VolumeManager::Instance 33. SLOGEquotUnable to create VolumeManagerquot 34. exit1 35. 36. 37. / 38. 实例化nm对象NetlinkManager类调用自身的Instance函数new了一个对象给nm。
39.
源码 40. NetlinkManager NetlinkManager::Instance 41. if sInstance 42. sInstance new NetlinkManager 43. return sInstance 44. 45. / 46. if nm NetlinkManager::Instance 47. SLOGEquotUnable to create NetlinkManagerquot 48. exit1 49. 50. 51. / 52. 实例化cl对象 53. vm-gtsetBroadcasterSocketListener cl 54. setBroadcaster函数将VolumeManager的成员变量mBroadcaster设置成cl这两个变量都是 55. SocketListener的指针类型命令执行状态广播函数就会调用这个SocketListener指针来调用 56. SocketListener类的广播函数 57. 为什么SocketListener类能强制转换CommandListener类呢 58. 原因继承关系CommandListener子类 --gt FrameworkListener子类 --gt SocketListener父类 59. 将子类强制转换为父类是没错的。
60. / 61. cl new CommandListener 62. vm-gtsetBroadcasterSocketListener cl 63. nm-gtsetBroadcasterSocketListener cl 64. 65. / 66. 调用start函数启动存储设备的管理类看了
源码这函数没干什么事估计去哪打酱油了。
67.
源码 68. int VolumeManager::start 69. return 0 70. 71. / 72. if vm-gtstart 73. SLOGEquotUnable to start VolumeManager squot strerrorerrno 74. exit1 75. 76. 77. / 78. process_config函数用来解析/etc/vold.fstab的配置文件从代码可以看出配置文件的参数 79. 以空格和制表格Tab键分隔系统启动起来分析该配置文件挂载相应的分区相当于 80. Linux系统的/etc/fstab文件。
81. / 82. if process_configvm 83. SLOGEquotError reading configuration s... continuing anywaysquot strerrorerrno 84. 85. 86. / 87. nm对象调用start函数开启了一个线程用来监听底层的uevent事件这start函数干的事就 88. 多了主要是打开一个udp套接字循环监听底层事件。
线程里面使用了Select函数来处理 89. 套接字这设计到fd_set结构体等等的使用 90. 当捕获到uevent事件vold会将该事件通知给Framework层Framework进行判断然后再 91. 下发操作命令。
92. / 93. if nm-gtstart 94. SLOGEquotUnable to start NetlinkManager squot strerrorerrno 95. exit1 96. 97. 98. coldbootquot/sys/blockquot 99. 100. / 101. 下面是判断
Android系统是否处于ums状态ums是大容量存储的意思这是
Android系统 102. 的OTG功能。
OTG是on-the-go的简称主要提供与pc机的连接 103. notifyUmsConnected函数将ums的状态通知给Framework层于是Framework与UI配合弹出 104. 一个与pc机连接的交互界面。
105. / 106. 107. FILE fp 108. char state255 109. 110. if fp fopenquot/sys/devices/virtual/switch/usb_mass_storage/statequotquotrquot 111. if fgetsstate sizeofstate fp 112. if strncmpstate quotonlinequot 6 113. vm-gtnotifyUmsConnectedtrue 114. else 115. vm-gtnotifyUmsConnectedfalse 116. 117. else 118. SLOGEquotFailed to read switch state squot strerrorerrno 119. 120. 121. fclosefp 122. else 123. SLOGWquotNo UMS switch availablequot 124. 125. 126. 127. / 128. 上面的准备工作已做完现在是vold比较重要的一个处理线程 129. startListener是CommandListener类的父类的函数该函数用于开启监听线程监听 130. Framework层下发给vold的命令然后调用相应的命令操作存储设备。
131. / 132. if cl-gtstartListener 133. SLOGEquotUnable to start CommandListener squot strerrorerrno 134. exit1 135. 136. 137. / 138. 进入一个循环让vold保持守护进程的状态 139. vold的主要工作是由nm-gtstart和cl-gtstartListener两个线程共同完成这两个处理线程 140. 中间需要Framework来充当桥梁与boss的身份Framework是管理这些磁盘的boss。
141. / 142. while1 143. sleep1000 144. 145. 146. SLOGIquotVold exitingquot 147. exit0 148. 149. 150. / 151. 以下这两个函数不重要也就是打开/sys/block目录处理一些事情这俩函数用来给vold打杂 152. 社会阶级比较低o∩_∩o 哈哈。
153. 里面有几个函数是bionic库提供的用得比较少。
154. / 155. static void do_coldbootDIR d int lvl 156. 157. struct dirent de 158. int dfd fd 159. 160. dfd dirfdd 161. 162. fd openatdfd quotueventquot O_WRONLY 163. iffd gt 0 164. writefd quotaddnquot 4 165. closefd 166. 167. 168. whilede readdird 169. DIR d2 170. 171. if de-gtd_name0 . 172. continue 173. 174. if de-gtd_type DT_DIR ampamp lvl gt 0 175. continue 176. 177. fd openatdfd de-gtd_name O_RDONLY O_DIRECTORY 178. iffd lt 0 179. continue 180. 181. d2 fdopendirfd 182. ifd2 0 183. closefd 184. else 185. do_coldbootd2 lvl 1 186. closedird2 187. 188. 189. 190. 191. static void coldbootconst char path 192. 193. DIR d opendirpath 194. ifd 195. do_coldbootd 0 196. closedird 197. 198. 199. 200. / 201. 该函数用来解析/etc/vold.fstab配置文件文本的处理 202. 可能不同的
源码版本有点差异 203. strsep是字符串的分割函数可以看出该函数是以quot tquot来分割t前面有一空格分割空格 204. 或制表格所以配置文件里面空格与tab键来分割都行 205. strsep不是ANSI C的函数但它用来取代strtok函数strtok是线程不安全的函数。
206. / 207. static int process_configVolumeManager vm 208. FILE fp 209. int n 0 210. char line255 211. 212. if fp fopenquot/etc/vold.fstabquot quotrquot 213. return -1 214. 215. 216. whilefgetsline sizeofline fp 217. char next line 218. char type label mount_point 219. 220. n 221. linestrlenline-1 0 222. 223. if line0 line0 0 224. continue 225. 226. if type strsepampnext quot tquot 227. SLOGEquotError parsing typequot 228. goto out_syntax 229. 230. if label strsepampnext quot tquot 231. SLOGEquotError parsing labelquot 232. goto out_syntax 233. 234. if mount_point strsepampnext quot tquot 235. SLOGEquotError parsing mount pointquot 236. goto out_syntax 237. 238. 239. if strcmptype quotdev_mountquot 240. DirectVolume dv NULL 241. char part sysfs_path 242. 243. if part strsepampnext quot tquot 244. SLOGEquotError parsing partitionquot 245. goto out_syntax 246. 247. if strcmppart quotautoquot ampamp atoipart 0 248. SLOGEquotPartition must either be auto or 1 based index instead of squot part 249. goto out_syntax 250. 251. / 252. 如果配置文件指定为auto则为自动挂载存储设备在实例化DirectVolume的对象传递-1 253. 进去否则将分区序数part传进去 254. / 255. if strcmppart quotautoquot 256. dv new DirectVolumevm label mount_point -1 257. else 258. dv new DirectVolumevm label mount_point atoipart 259. 260. 261. whilesysfs_path strsepampnext quot tquot 262. / 263. 将存储设备在/sys/对应的路径添加进PathCollection容器该容器为“char ”类型 264. 在/sys/里面可以获取到存储设备的热插拔事件所以DirectVolume类的主要工作就是针对 265. .