VOLD(Volume Daemon)是 Android 系统中负责管理外部存储设备的守护进程,主要处理存储设备的挂载、卸载和格式化等操作。
主要功能
- 存储设备管理:
- 检测和识别外部存储设备(如 SD 卡、USB 存储设备)。
- 挂载与卸载:
- 文件系统支持:
- 支持多种文件系统(如 FAT32、exFAT、NTFS、ext4 等)。
- 权限管理:
Vold主要包含NetLinkManager(nm)、VolumeManager(vm)、VoldNativeService。
NetLinkManager:主要负责监听来自kernel的UEvent
VolumeManager:主要是配置相关的选项并告知上层,并接受上层所返回的消息
VoldNativeService:真正去实现挂载的服务,会创建相应的文件夹,设定U盘权限,是否开启FUSE等等
1. 卷管理
卷通常指的是存储设备或存储介质上的一个独立区域,用于存储文件和数据。在操作系统中,一个硬盘可以被分为多个分区,每个分区可以被格式化为一个独立的卷。用直白的话说就是卷是存储设备上的一部分,是可以直接拿来存储文件的。vold管理着存储设备 (比如SD卡、U盘) 所有的卷,其中卷又有虚拟卷 (EmulatedVolume) 、obb卷 (ObbVolume) 、私有卷 (PrivateVolume)、公有卷 (public Volume)、stub卷 (StubVolume)
2. Vold模块的启动
vold模块启动流程如下:

vold启动在init.rc中:
| Java service vold /system/bin/vold \ --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \ --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0 class core ioprio be 2 writepid /dev/cpuset/foreground/tasks shutdown critical group root reserved_disk |
vold代码在/system/vold下面
函数入口是main函数:
| Java /system/vold/main.cpp int main(int argc, char** argv) {
... VolumeManager* vm; NetlinkManager* nm; parse_args(argc, argv); sehandle = selinux_android_file_context_handle(); if (sehandle) {
selinux_android_set_sehandle(sehandle); } // 创建目录,用于放置后面建立的vold节点 mkdir("/dev/block/vold", 0755); // VolumeManager负责Volume的一些管理 if (!(vm = VolumeManager::Instance())) {
LOG(ERROR) << "Unable to create VolumeManager"; exit(1); } // NetlinkManager负责与内核之间的通信 if (!(nm = NetlinkManager::Instance())) {
LOG(ERROR) << "Unable to create NetlinkManager"; exit(1); } if (android::base::GetBoolProperty("vold.debug", false)) {
vm->setDebug(true); } // 启动VolumeManager if (vm->start()) {
PLOG(ERROR) << "Unable to start VolumeManager"; exit(1); } VoldConfigs configs = {}; // 解析fstab文件 if (process_config(vm, &configs)) {
PLOG(ERROR) << "Error reading configuration... continuing anyways"; } android::hardware::configureRpcThreadpool(1, false /* callerWillJoin */); // 创建VoldNativeService if (android::vold::VoldNativeService::start() != android::OK) {
LOG(ERROR) << "Unable to start VoldNativeService"; exit(1); } ATRACE_END(); LOG(DEBUG) << "VoldNativeService::start() completed OK"; // 启动NetlinkManager if (nm->start()) {
PLOG(ERROR) << "Unable to start NetlinkManager"; exit(1); } ... android::IPCThreadState::self()->joinThreadPool(); exit(0); } |
2.1 VolumeManager#start
| Java int VolumeManager::start() {
ATRACE_NAME("VolumeManager::start"); // 始终从头开始,卸载我们拥有的目录中的所有内容,以防崩溃 unmountAll(); Devmapper::destroyAll(); Loop::destroyAll(); CHECK(mInternalEmulatedVolumes.empty()); // 构造出内置存储目录/data/media auto vol = std::shared_ptr<android::vold::VolumeBase>( new android::vold::EmulatedVolume("/data/media", 0)); vol->setMountUserId(0); vol->create(); mInternalEmulatedVolumes.push_back(vol); // 构造虚拟磁盘 updateVirtualDisk(); return 0; } |
2.2 VoldNativeService#start
| Java status_t VoldNativeService::start() {
IPCThreadState::self()->disableBackgroundScheduling(true); status_t ret = BinderService<VoldNativeService>::publish(); if (ret != android::OK) {
return ret; } sp<ProcessState> ps(ProcessState::self()); ps->startThreadPool(); ps->giveThreadPoolName(); return android::OK; } |
VoldNativeService负责连接vold与StorageManagerService
2.3 NetlinkManager#start
| Java int NetlinkManager::start() {
struct sockaddr_nl nladdr; int sz = 64 * 1024; int on = 1; memset(&nladdr, 0, sizeof(nladdr)); nladdr.nl_family = AF_NETLINK; nladdr.nl_pid = getpid(); nladdr.nl_groups = 0xffffffff; // 注册UEVENT事件,用于接收内核信息 if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)) < 0) {
PLOG(ERROR) << "Unable to create uevent socket"; return -1; } if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) && (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) {
PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option"; goto out; } if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option"; goto out; } if (bind(mSock, (struct sockaddr*)&nladdr, sizeof(nladdr)) < 0) {
PLOG(ERROR) << "Unable to bind uevent socket"; goto out; } // NetlinkHandler用于对接收到的内核消息进行处理 mHandler = new NetlinkHandler(mSock); // 开始监听内核消息 if (mHandler->start()) {
PLOG(ERROR) << "Unable to start NetlinkHandler"; goto out; } return 0; out: close(mSock); return -1; } |
2.3.1 NetlinkHandler#start
| C++ int NetlinkHandler::start() {
return this->startListener(); } |
这里的startListener是SocketListener的一个成员方法,NetlinkHandler继承了NetlinkListener,NetlinkListener继承了SocketListener:

2.3.1.1 SocketListener#startListener
| C++ int SocketListener::startListener() {
return startListener(4); } int SocketListener::startListener(int backlog) {
// mSocket在创建NetlinkHandler时赋值了 if (!mSocketName && mSock == -1) {
SLOGE("Failed to start unbound listener"); errno = EINVAL; return -1; } else if (mSocketName) {
if ((mSock = android_get_control_socket(mSocketName)) < 0) {
SLOGE("Obtaining file descriptor socket '%s' failed: %s", mSocketName, strerror(errno)); return -1; } SLOGV("got mSock = %d for %s", mSock, mSocketName); fcntl(mSock, F_SETFD, FD_CLOEXEC); } if (mListen && listen(mSock, backlog) < 0) {
SLOGE("Unable to listen on socket (%s)", strerror(errno)); return -1; } else if (!mListen) mClients[mSock] = new SocketClient(mSock, false, mUseCmdNum); //建立管道,用于后面的关闭监听循环 if (pipe2(mCtrlPipe, O_CLOEXEC)) {
SLOGE("pipe failed (%s)", strerror(errno)); return -1; } if (pthread_create(&mThread, nullptr, SocketListener::threadStart, this)) {
SLOGE("pthread_create (%s)", strerror(errno)); return -1; } return 0; } void *SocketListener::threadStart(void *obj) {
SocketListener *me = reinterpret_cast<SocketListener *>(obj); me->runListener(); pthread_exit(nullptr); return nullptr; } |
2.3.1.2 SocketListener#runListener
| C++ void SocketListener::runListener() {
while (true) {
std::vector<pollfd> fds; pthread_mutex_lock(&mClientsLock); fds.reserve(2 + mClients.size()); fds.push_back({.fd = mCtrlPipe[0], .events = POLLIN}); if (mListen) fds.push_back({.fd = mSock, .events = POLLIN}); for (auto pair : mClients) {
// NB: calling out to an other object with mClientsLock held (safe) const int fd = pair.second->getSocket(); if (fd != pair.first) SLOGE("fd mismatch: %d != %d", fd, pair.first); fds.push_back({.fd = fd, .events = POLLIN}); } pthread_mutex_unlock(&mClientsLock); SLOGV("mListen=%d, mSocketName=%s", mListen, mSocketName); int rc = TEMP_FAILURE_RETRY(poll(fds.data(), fds.size(), -1)); if (rc < 0) {
SLOGE("poll failed (%s) mListen=%d", strerror(errno), mListen); sleep(1); continue; } if (fds[0].revents & (POLLIN | POLLERR)) {
char c = CtrlPipe_Shutdown; TEMP_FAILURE_RETRY(read(mCtrlPipe[0], &c, 1)); if (c == CtrlPipe_Shutdown) {
break; } continue; } if (mListen && (fds[1].revents & (POLLIN | POLLERR))) {
int c = TEMP_FAILURE_RETRY(accept4(mSock, nullptr, nullptr, SOCK_CLOEXEC)); if (c < 0) {
SLOGE("accept failed (%s)", strerror(errno)); sleep(1); continue; } pthread_mutex_lock(&mClientsLock); mClients[c] = new SocketClient(c, true, mUseCmdNum); pthread_mutex_unlock(&mClientsLock); } // Add all active clients to the pending list first, so we can release // the lock before invoking the callbacks. std::vector<SocketClient*> pending; pthread_mutex_lock(&mClientsLock); const int size = fds.size(); for (int i = mListen ? 2 : 1; i < size; ++i) {
const struct pollfd& p = fds[i]; if (p.revents & (POLLIN | POLLERR)) {
auto it = mClients.find(p.fd); if (it == mClients.end()) {
SLOGE("fd vanished: %d", p.fd); continue; } SocketClient* c = it->second; pending.push_back(c); c->incRef(); } } pthread_mutex_unlock(&mClientsLock); for (SocketClient* c : pending) {
// Process it, if false is returned, remove from the map SLOGV("processing fd %d", c->getSocket()); // 处理消息 if (!onDataAvailable(c)) {
release(c, false); } c->decRef(); } } } |
这里就是kernel与native通信的接口,内核上报u盘插入事件后就会通过这里通知到上层。
3. StorageManagerService的启动
StorageManagerService通过SystemServer启动,启动完成后调用ServiceManager.addService注册服务
| C++ /frameworks/base/services/core/java/com/android/server/StorageManagerService.java public void onStart() {
mStorageManagerService = new StorageManagerService(getContext()); publishBinderService("mount", mStorageManagerService); mStorageManagerService.start(); } protected final void publishBinderService(String name, IBinder service, boolean allowIsolated, int dumpPriority) {
ServiceManager.addService(name, service, allowIsolated, dumpPriority); } |
3.1 Start
| C++ private void start() {
// 连接文件系统监控服务 connectStoraged(); // 连接vold connectVold(); } |
3.2 connectVold
| C++ private void connectVold() {
IBinder binder = ServiceManager.getService("vold"); ... if (binder != null) {
// 获取native层服务端索引 mVold = IVold.Stub.asInterface(binder); try {
// 设置监听 mVold.setListener(mListener); } catch (RemoteException e) {
mVold = null; Slog.w(TAG, "vold listener rejected; trying again", e); } } else {
Slog.w(TAG, "vold not found; trying again"); } if (mVold == null) {
BackgroundThread.getHandler().postDelayed(() -> {
connectVold(); }, DateUtils.SECOND_IN_MILLIS); } else {
restoreLocalUnlockedUsers(); onDaemonConnected(); } } |
3.2.1 VoldNativeService#setListener
这里通过mVold调用了VoldNativeService的setListener,在system/vold/binder/android/os/IVold.aidl文件中声明了mvold可以调用的函数。
| C++ binder::Status VoldNativeService::setListener( const android::sp<android::os::IVoldListener>& listener) {
ENFORCE_SYSTEM_OR_ROOT; ACQUIRE_LOCK; VolumeManager::Instance()->setListener(listener); return Ok(); } VolumeManager.cpp void setListener(android::sp<android::os::IVoldListener> listener) { mListener = listener; } |
这里在VolumeManager里注册了一个监听回调,对应的监听事件在system/vold/binder/android/os/IVoldListener.aidl里:
| C++ package android.os; /** {@hide} */ oneway interface IVoldListener {
void onDiskCreated(@utf8InCpp String diskId, int flags); void onDiskScanned(@utf8InCpp String diskId); void onDiskMetadataChanged(@utf8InCpp String diskId, long sizeBytes, @utf8InCpp String label, @utf8InCpp String sysPath); void onDiskDestroyed(@utf8InCpp String diskId); void onVolumeCreated(@utf8InCpp String volId, int type, @utf8InCpp String diskId, @utf8InCpp String partGuid, int userId); void onVolumeStateChanged(@utf8InCpp String volId, int state); void onVolumeMetadataChanged(@utf8InCpp String volId, @utf8InCpp String fsType, @utf8InCpp String fsUuid, @utf8InCpp String fsLabel); void onVolumePathChanged(@utf8InCpp String volId, @utf8InCpp String path); void onVolumeInternalPathChanged(@utf8InCpp String volId, @utf8InCpp String internalPath); void onVolumeDestroyed(@utf8InCpp String volId); } |
3.2.2 onDaemonConnected
onDaemonConnected会发送一个消息,最后调到handleDaemonConnected:
| C++ private void handleDaemonConnected() {
initIfBootedAndConnected(); resetIfBootedAndConnected(); // On an encrypted device we can't see system properties yet, so pull // the system locale out of the mount service. if ("".equals(VoldProperties.encrypt_progress().orElse(""))) {
copyLocaleFromMountService(); } } |
3.2.2.1 resetIfBootedAndConnected
| C++ private void resetIfBootedAndConnected() {
Slog.d(TAG, "Thinking about reset, mBootCompleted=" + mBootCompleted + ", mDaemonConnected=" + mDaemonConnected); // 等待启动完成并且连接上storage或vold守护服务 if (mBootCompleted && mDaemonConnected) {
... try {
... Slog.i(TAG, "Resetting vold..."); mVold.reset(); Slog.i(TAG, "Reset vold"); ... for (int userId : systemUnlockedUsers) {
mVold.onUserStarted(userId); mStoraged.onUserStarted(userId); } ... } } |
3.2.2.2 VoldManager#reset
| C++ int VolumeManager::reset() {
// Tear down all existing disks/volumes and start from a blank slate so // newly connected framework hears all events. for (const auto& vol : mInternalEmulatedVolumes) {
vol->destroy(); } mInternalEmulatedVolumes.clear(); // 更新已存在的disk for (const auto& disk : mDisks) {
disk->destroy(); disk->create(); } // 更新virtualdisk updateVirtualDisk(); mAddedUsers.clear(); mStartedUsers.clear(); return 0; } |
更新disk的目的是为了回调Framework这些disk已创建。
3.2.2.3 VoldManager#onUserStarted
| C++ int VolumeManager::onUserStarted(userid_t userId) {
LOG(INFO) << "onUserStarted: " << userId; if (mStartedUsers.find(userId) == mStartedUsers.end()) {
createEmulatedVolumesForUser(userId); } mStartedUsers.insert(userId); createPendingDisksIfNeeded(); return 0; } void VolumeManager::createPendingDisksIfNeeded() {
|