android vold学习总结
- 格式:doc
- 大小:64.50 KB
- 文档页数:4
vold学习总结V old(volume daemon):源码路径android/system/vold,部分引用代码位于android/system/core/libsysutils/src,android/system/core/include/sysutils/下。
它用于管理和控制android平台的外部设备,包括u盘、sd卡等的插入,拔出和格式化等。
V old为守护进程,由init进程启动,V old的框架如下图所示:Linux kernel与vold进程通过netlink机制进行跨进程通信,vold中的NetlinkManager 接收来自linux kernel上报的uevent事件,然后将其转换成一个NetlinkEvent类型,并调用V olumeManager类的相应方法进行处理,V olumeManager会将处理的结果发送给MountService,VolumeManager与MountService之间通过CommandListener机制进行通信,本质是通过socket进行跨进程通信,MountService运行在SystemServer进程中。
Uevent事件内容就是一个字符串,linux kernel在下列两种情况下会上报uevent事件:1.外设状态发生变化触发,当有U盘、sd卡等外设的插拔动作时,都会引起linux kernel 上报uevent事件,如果vold在外设状态发生变化之前已经建立了netlink连接,就能收到相应的uevent事件。
2.在/sys目录下会有一个叫做uevent的文件,往该文件中写入特定的数据,也会触发kernel发送和该设备相关的uevent事件,这个由应用层触发,例如vold启动时,会往uevent 文件中写入数据,它就会触发linux kernel发送uevent事件,这样vold就能获取设备的当前信息。
在etc/目录下有个vold.fstab文件(实际上该文件是在system/etc目录下,它在system/core/rootdir/init.rc中有配置:symlink /system/etc /etc,通过软链接而链接到etc目录下),该文件是android系统与硬件平台交互的接口,用户可以手动配置该文件,在android\system\core\rootdir\etc\下有个vold.fstab文件,它描述了vold.fstab文件配置挂载设备的模板,dev_mount <label> <mount_point> <part> <sysfs_path1...>其中part表示分区,值为auto或具体的分区编号,auto表示挂载该设备上的第一个分区(该设备只有一个分区),分区编号表示使用该设备上的第几个分区,sysfs_path表示设备在sys目录下的设备路径(可多个),各个参数之间用全部用空格或tab键隔开。
注:sysfs文件系统是linux中一种特殊的文件系统,用于将系统中的设备组织成层次结构,并向用户模式程序提供详细的内核数据结构信息。
sysfs_path表示vold监测的路径,当有设备插入时,在监测的路径下会多出一个文件夹,该文件夹中描述了插入设备的各种ID信息。
在sys目录下有多个目录:block(系统中的所有块设备)、bus(系统中的所有总线设备)、devices(系统中的所有设备层次结构)、drivers(系统中的所有驱动)等。
dev_mount sdcard1 /mnt/sdcard auto /devices/platform/sdhci-tegra.2/mmc_host/mmc1/mmc1当设备中出入sd卡后,在dev/block目录下会多出几个设备节点,表示sd卡驱动已经加载成功,一般会多出两个设备节点mmcblk0和mmcblk0p1节点,其中mmcblk0表示第一个sd卡设备,mmcblk0p1表示第一个sd卡设备的第一个分区,真正挂载到系统中的是mmcblk0p1而非mmcblk0,如果手动使用mount挂载时,不能直接挂载设备,而是选择挂载设备的分区,例如mount -t vfat /dev/block/mmcblk0p1 sdcard关键点:1.V old的main方法中会调用process_config()方法解析vold.fstab文件,根据文件内容去配置V olumeManager对象。
2.当linux kernel上报一个uevent事件时,NetlinkManager会处理该事件,实际是它是调用NetlinkHandler类处理的,NetlinkHandler类的继承层次关系:NetlinkHandler继承自NetlinkListener,而NetlinkListener又继承自SocketListener。
在NetlinkListener类的onDataAvailable()方法中,会将一个原始的uevent事件内容解析为NetlinkEvent类,并调用NetlinkHandler类的onEvent()方法。
3.从kernel上报uevent事件时,vold的处理简单流程为:SocketListener::runListener()->NetlinkListener::onDataAvailable()->NetlinkHandler::onEvent()->VolumeManager::handleBloc kEvent()->DirectVolume::handleBlockEvent()->CommandListener::sendBroadcast()。
4.vold与MountService进行通信的简单处理流程为:SocketListener::runListener()->FrameworkListener::onDataAvailable()->FrameworkListener ::dispatchCommand()->***Cmd:: runCommand()。
在dispatchCommand()中会根据命令字符串内容不同调用相应的VoldCommand子类的runCommand()进行处理,进而调用VolumeManager的相应方法。
经过V olumeManager处理的uevent类型主要有:block、switch、usb_composite、battery、power_supply,在DirectV olume的handleBlockEvent()方法中,会根据设备类型和执行的动作(add/remove/change)执行相应的函数:handleDiskAdded()、handlePartitionAdded()、handleDiskRemoved()、handlePartitionRemoved()等,在这些方法中,最终会调用mVm->getBroadcaster()->sendBroadcast()方法,实际调用了CommandListener类的sendBroadcast()方法,该方法利用socket通信将消息发送给MountService类。
5.当vold发送消息给MountService后,会触发MountService类的onEvent()方法调用(由NativeDaemonConnector调用)。
在onEvent()方法中,会发送相应广播消息,并且会调用相应接口触发通知。
StorageManager可看做MountService在客户端的代理类。
应用程序可以通过调用StorageManager类的相应方法,例如注册监听器获取外设的插拔通知。
对于应用程序来说,有两种方式获取外设插拔通知,一是通过StorageManager类的registerListener()注册监听器,二是注册广播接收器接收相应的广播消息。
6.MountService.java中会读取storage_list.xml文件(位于framework/res/res/xml/),7.Android系统中使用UeventObserver类可以监控linux kernel上报的uevent事件,利用UeventObserver检测外部设备插拔的设备有:BatteryService:检测充电器的插拔。
PhoneWindowManager:检测hdmi的插拔。
WiredAccessoryManager:检测有线耳机的插拔。
DockObserver:检测底座的插拔。
UsbDeviceManager:Android系统作为从设备,连接到主设备pc的检测。
读取Uevent事件代码:hardware\libhardware_legacy\uevent\uevent.c.SocketListener:处理套接字监听器的基类,vold利用两个socket分别与上层应用和linux kernel进行通信,与上层应用进行通信时,利用的是CommandListener,与linux kernel进行通信利用的是NetlinkHandler,通信机制用的是netlink socket机制。
SocketListener的构造函数中指定了两个参数,分别表示socket名字和是否监听套接字(根据定义变量mListen判断)。
SocketListener类主要有以下几个方法:startListener():启动监听器,该方法中会创建一个套接字,并启动一个子线程处理socket通信,子线程中会进入一个死循环,然后利用select机制来监听多个套接字,监听套接字有三种:来自客户端的连接请求,客户端发送过来的数据,管道读端。
如果变量mListen为false,是不会监听来自客户端的连接请求的。
管道读端用于确定是否退出子线程操作。
当有客户端发送数据过来时,select()会返回,会调用onDataAvailable()进行处理。
onDataAvailable是虚函数,由其子类实现。
stopListener():停止监听器,通过往管道中写数据来退出socket通信的子线程。
sendBroadcast():遍历所有连接的客户端SocketClient实例,并调用每个实例的sendMsg()方法将消息发送给客户端。
FrameworkListener:继承自SocketListener,指定监听套接字变量mListen为true。
onDataAvailable()中从socket buffer中获取客户端发送过来的数据,并调用dispatchCommand(),在dispatchCommand()中会解析数据,然后比较command的名字与哪个FrameworkCommand名字匹配,并调用匹配的FrameworkCommand子类的runCommand()方法。