USB Storage
1. Vold 简介
1.1 udev 的由来
udev 是 Linux2.6 内核里的一个功能,它替代了原来的 devfs,成为当前 Linux 预设
的设备管理工具。udev 以守护进程的形式运行,通过侦听内核发出来的 uevent 来管理
/dev 目录下的设备文件。不像之前的设备管理工具,udev 在用户空间 (user space) 运
行,而不在内核空间 (kernel space) 运行。
devfs 存在的主要的问题是它处理设备检测、创建和命名的方式,其中设备节点的命名可
能是最严重的问题。一般可接受的方式是,如果设备名 是可配置的,那么设备命名策略
应该由系统管理员决定,而不是由某些开发者强制规定。devfs 文件系统还存在竞争条件
(race conditions) 的问题,这是它天生的
设计
领导形象设计圆作业设计ao工艺污水处理厂设计附属工程施工组织设计清扫机器人结构设计
缺陷,不对内核做彻底的修改就无法修正这
个问题。所以 udef 应运而生。
udev 能够实现所有 devfs 实现的功能。具有以下优点:
1) dynamic replacement for /dev。作为 devfs 的替代者,传统的 devfs 不能动态
分配 major 和 minor 的值,而 major 和 minor 非常有限,很快就会用完了。 udev
能够像 DHCP 动态分配 IP 地址一样去动态分配 major 和 minor。
2) device naming。提供设备命名持久化的机制。传统设备命名方式不具直观性,像
/dev/hda1 这样的名字肯定没有 boot_disk 这样的名字直观。udev 能够像 DNS
解析域名一样去给设备指定一个有意义的名称。
3) API to access info about current system devices 。提供了一组易用的 API 去
操作 sysfs,避免重复实现同样的代码,
但 udev 运行在用户模式中,而 devfs 运行在内核中。udev 只支持 linux-2.6 内核,因
为 udev 严重依赖于 sysfs 文件系统提供的信息,而 sysfs 文件系统只在 linux-2.6 内核中
才有。
1.2 Vold 的产生
Vold 的全称是 Volume Daemon。在 android 中,取代 udev 的是 vold,我们这里不去过
多的讨论为什么 android 不继续使用 udev,但要知道 vold 的机制和 udev 是一样的,理
解了 udev,也就理解了 vold。android 一出生就没有尊守传统 linux 的许多
标准
excel标准偏差excel标准偏差函数exl标准差函数国标检验抽样标准表免费下载红头文件格式标准下载
,当然也
不能指望 udev 能很好的服务于 android。android 小区的选择是别起炉灶,为 android
定做一套 udev,这就是 vold 了。无论是 udev 还是 vold,都是基于 sysfs 的,sysfs 为内核
与用户层的通讯提供了一种全新的方式,并将这种方式加以规范。kernel 层能检测到有新
的设备接入,并能为之加载相应的驱动,但如何
通知
关于发布提成方案的通知关于xx通知关于成立公司筹建组的通知关于红头文件的使用公开通知关于计发全勤奖的通知
用户层呢?这就是 sysfs 的工作,内核
中的 sysfs机制要求当有新的驱动加载时给用户层发送相应的 event.但这些 event只尽告
知的义务,具体怎么处理,这就是 vold 的事了。对于用户层而言,我们无需关心 sysfs 的
细节,只要知道 sysfs 能向用户层提供什么就行了。首先,我们要知道如何接收来自内核的
event.Netlink socket 大家应该不会陌生吧,socket 这套东西不仅能用于网络间的通讯,
也用能用于进程间的通讯,像这种内核态与用户沟通的活,自然也少不了它。关于这个部分,
我们将在 Vold 通信仲介绍。关于 Vold 的主要作用,如下图所示:
NativeDaemonConnector
MountService Java空间
C++空间
Volume Daemon
Linux Kernel
sysfs
uevent Function call
庫函數
onEvent Command
onEventcommand
Volume Daemon 简介
Android 的 volume 服务主要是用来管理 usb/sd 卡等外部存储设备。平台可以对外部存
储设备进行操作和轮询状态,当外部存储设备状态发生变化时,volume 服务也会实时报
告平台。
2. Vold 功能分析
2.1. Vold 启动
Volume Daemon 实在 android init 进程中启动的(关于 android 启动有其他同事介绍)。在 init
进程中将解析 init.rc 文件。在该文件中有启动 Vold 的配置。见下图:
在这里将启动 Vold Daemon,并且创建一个 socket。改 socket 主要是为了与 framework 层通
信。
2.2 Vold 内部架构
NetLinkManager
CommandListener
Volume
DirectVolume
AutoVolume
SocketListener
VolumeManager
Vold(Volume Daemon)的内部框架如上图所示。Vold 处理过程大致分为三步:创建连
结、引导和事件处理。下面将结合上图对 vold 工作流程进行详细分析。
2.2.1. 创建连结
在 vold 作为一个守护进程,一方面接受驱动的信息,并把信息传给应用层;另一方面接受
上层的命令并完成相应。所以这里的连结一共有两条:
1) vold socket: 负责 vold 与 framework 层的信息传递;
2) 接受 sysfs uevent 的 socket: 负责接受 kernel 的信息;
Vold socket 是在 init 进程启动 Volume Daemon时创建的,这是一个用于和 framework
层通信的 socket,在 android 系统中叫做 Localsocket,framework 曾通过 JNI 机制调
用 C/C++空间函数,具体过程如下图:
在 framework 层的 NativeDaemonConnector 类中调用下面代码
其中 mSocket 值为“vold”表示要获得 socket 的名字,该 socket 上上所述,是在 vold
被 init 的时候创建的,并且保存为全局变量。在 socket.connect()中调用
LocalSocketImpl.create_native()方法。改方法通过一个函数对应表,调用相应的
C/C++函数。该表如下所示:
关于 JNI 由其他同事详细介绍,这里不展开,只要知道用 Java JNI 机制调用的是 C/C++
函数。这个 framework 层和 Vold 中分别持有同一个 socket 实例,这样上层通信就建立
起来了。
而与内核通信的 socket 是在 vold main 函数中创建的。在 main 函数中,vold 将创建两
个单例,VolumeManager 和 NetLinkManager,与内核通信的 socket 就在其中创建。
这样 Volume Daemon 与 Kernel、framework 层的通信框架就建立了。关于 Volume
Daemon 的内部通行将在下一节中详细解释。
2.2.2. 引导
这里主要是在 vold 启动时,对现有外设存储设备的处理。首先,要载入并解析 vold.fstab。
vold.fstab 如下图所示:
图中红色部分标记可配置的部分。我们在 Porting 的时候可以设置,系统可以挂载 USB
Storage 端口的数目。配置格式为:
dev_mount 命令 标签 挂载点 子分区 设备在 sysfs 文件系统下的路径(可多个)
以Android X86 froyo中的 vold.fstab为例,它仅仅为系统配置了一个外接USB Storage
埠,如上图红色部分所示,其意义对应下表。
dev_mount 命令: dev_mount