一、概况
在Android 中,当SD卡U盘等外部存储器插入系统之后,系统会自动挂载。Vold 就是负责挂载的,vold 的全称是volume daemon。实际上是负责完成系统的CDROM,USB 大容量存储,MMC 卡等扩展存储的挂载任务自动完成的守护进程。它提供的主要特点是支持这些存储外设的热插拔。
Vold框架图
关键文件:
- main.cpp,vold的入口函数,系统起来会只执行vold的可执行文件,调到这个main函数中。
- NetlinkManager.cpp位于源码位置/system/vold/NetlinkManager.cpp。该类的主要通过引用NetlinkHandler类中的onEvent()方法来接收来自内核的事件消息,NetlinkHandler位于/system/vold/NetlinkHandler.cpp。
- VolumeManager:位于源码位置/system/vold/VolumeManager.cpp。该类的主要作用是接收经过NetlinkManager处理过后的事件消息。
- DirectVolume:位于/system/vold/DirectVolume.cpp。该类的是一个工具类,主要负责对传入的事件进行进一步的处理,block事件又可以分为:Add,Removed,Change,Noaction这四种。
- Volume:Volume.cpp位于/system/vold/Volume.cpp,该类是负责SD卡挂载的主要类。Volume.cpp主要负责检查SD卡格式,以及对复合要求的SD卡进行挂载,并通过Socket将消息SD卡挂载的消息传递给NativeDaemonConnector。
总的讲,vold程序需要分层三部分,第一部分为NetlinkManager,管理接受来自kernel的UEvent消息,第二部分为VolumeManager,主要负责处理来自NetlinkManager的消息和来自java层的消息,之后真正的挂载卸载动作就需要volume负责了。
二、vold进程
在Android 系统启动的时候,init进程会去解析vold.rc文件,在该文件中,有如下代码:
1 service vold /system/bin/vold \
2 --blkid_context=u:r:blkid:s0 --blkid_untrusted_context=u:r:blkid_untrusted:s0 \
3 --fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
4 class core
5 ioprio be 2
6 writepid /dev/cpuset/foreground/tasks
7 shutdown critical
8 group reserved_disk
定义了一个vold的service,去执行vold程序,并创建了一个名字为vold的socket,init进程解析完后就去执行vold程序,创建与java层通信的Socket。
在Android 源码/system/vold路径下的main.cpp,这个就是vold程序的入口,我们看看起main函数,代码如下:
int main() {
......
83 /* Create our singleton managers */
84 if (!(vm = VolumeManager::Instance())) {
85 LOG(ERROR) << "Unable to create VolumeManager";
86 exit(1);
87 }
88
89 if (!(nm = NetlinkManager::Instance())) {
90 LOG(ERROR) << "Unable to create NetlinkManager";
91 exit(1);
92 }
93
94 if (android::base::GetBoolProperty("vold.debug", false)) {
95 vm->setDebug(true);
96 }
97
98 if (vm->start()) {
99 PLOG(ERROR) << "Unable to start VolumeManager";
100 exit(1);
101 }
102
103 bool has_adoptable;
104 bool has_quota;
105 bool has_reserved;
106
107 if (process_config(vm, &has_adoptable, &has_quota, &has_reserved)) {
108 PLOG(ERROR) << "Error reading configuration... continuing anyways";
109 }
110
111 ATRACE_BEGIN("VoldNativeService::start");
112 if (android::vold::VoldNativeService::start() != android::OK) {
113 LOG(ERROR) << "Unable to start VoldNativeService";
114 exit(1);
115 }
116 ATRACE_END();
117
118 LOG(DEBUG) << "VoldNativeService::start() completed OK";
119
120 ATRACE_BEGIN("NetlinkManager::start");
121 if (nm->start()) {
122 PLOG(ERROR) << "Unable to start NetlinkManager";
123 exit(1);
124 }
...........
}
首先,在 main 函数中,需要创建 VolumeManager 和 NetlinkManager 的实例,里面就做了一些初始化的动作。
vm->start()
进行预制存储的挂载
146 int VolumeManager::start() {
147 ATRACE_NAME("VolumeManager::start");
148
149 // Always start from a clean slate by unmounting everything in
150 // directories that we own, in case we crashed.
151 unmountAll();
152
153 Devmapper::destroyAll();
154 Loop::destroyAll();
155
156 // Assume that we always have an emulated volume on internal
157 // storage; the framework will decide if it should be mounted.
158 CHECK(mInternalEmulated == nullptr);
//这里是sdcard/emulated分区
159 mInternalEmulated = std::shared_ptr<android::vold::VolumeBase>(
160 new android::vold::EmulatedVolume("/data/media"));
161 mInternalEmulated->create();
162
163 // Consider creating a virtual disk
164 updateVirtualDisk();
165
166 return 0;
167 }
nm→start()
与kennel建立联系
49 int NetlinkManager::start() {
50 struct sockaddr_nl nladdr;
51 int sz = 64 * 1024;
52 int on = 1;
53
54 memset(&nladdr, 0, sizeof(nladdr));
55 nladdr.nl_family = AF_NETLINK;
56 nladdr.nl_pid = getpid();
57 nladdr.nl_groups = 0xffffffff;
58
59 if ((mSock = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC,
60 NETLINK_KOBJECT_UEVENT)) < 0) {
61 PLOG(ERROR) << "Unable to create uevent socket";
62 return -1;
63 }
64
65 // When running in a net/user namespace, SO_RCVBUFFORCE will fail because
66 // it will check for the CAP_NET_ADMIN capability in the root namespace.
67 // Try using SO_RCVBUF if that fails.
68 if ((setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) &&
69 (setsockopt(mSock, SOL_SOCKET, SO_RCVBUF, &sz, sizeof(sz)) < 0)) {
70 PLOG(ERROR) << "Unable to set uevent socket SO_RCVBUF/SO_RCVBUFFORCE option";
71 goto out;
72 }
73
74 if (setsockopt(mSock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on)) < 0) {
75 PLOG(ERROR) << "Unable to set uevent socket SO_PASSCRED option";
76 goto out;
77 }
78
79 if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
80 PLOG(ERROR) << "Unable to bind uevent socket";
81 goto out;
82 }
83 //上报事件关键
84 mHandler = new NetlinkHandler(mSock);
85 if (mHandler->start()) {
86 PLOG(ERROR) << "Unable to start NetlinkHandler";
87 goto out;
88 }
89
90 return 0;
91
92 out:
93 close(mSock);
94 return -1;
95 }
建立联系后,kennel的事件上报将会回调至NetlinkHandler中的onEvent函数
43 void NetlinkHandler::onEvent(NetlinkEvent *evt) {
44 VolumeManager *vm = VolumeManager::Instance();
45 const char *subsys = evt->getSubsystem();
46
47 if (!subsys) {
48 LOG(WARNING) << "No subsystem found in netlink event";
49 return;
50 }
51
52 if (std::string(subsys) == "block") {
53 vm->handleBlockEvent(evt);
54 }
55 }
最终回到VolumeManager中的handleBlockEvent(NetlinkEvent *evt)函数
176 void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
177 std::lock_guard<std::mutex> lock(mLock);
178
179 if (mDebug) {
180 LOG(VERBOSE) << "----------------";
181 LOG(VERBOSE) << "handleBlockEvent with action " << (int) evt->getAction();
182 evt->dump();
183 }
184
185 std::string eventPath(evt->findParam("DEVPATH")?evt->findParam("DEVPATH"):"");
186 std::string devType(evt->findParam("DEVTYPE")?evt->findParam("DEVTYPE"):"");
187
188 if (devType != "disk") return;
189 //创建device信息
190 int major = std::stoi(evt->findParam("MAJOR"));
191 int minor = std::stoi(evt->findParam("MINOR"));
192 dev_t device = makedev(major, minor);
193 //区分事件
194 switch (evt->getAction()) {
195 case NetlinkEvent::Action::kAdd: { //添加
196 for (const auto& source : mDiskSources) {
197 if (source->matches(eventPath)) {
198 // For now, assume that MMC and virtio-blk (the latter is
199 // emulator-specific; see Disk.cpp for details) devices are SD,
200 // and that everything else is USB
201 int flags = source->getFlags();
202 if (major == kMajorBlockMmc
203 || (android::vold::IsRunningInEmulator()
204 && major >= (int) kMajorBlockExperimentalMin
205 && major <= (int) kMajorBlockExperimentalMax)) {
206 flags |= android::vold::Disk::Flags::kSd;
207 } else {
208 flags |= android::vold::Disk::Flags::kUsb;
209 }
210
211 auto disk = new android::vold::Disk(eventPath, device,
212 source->getNickname(), flags);
213 handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
214 break;
215 }
216 }
217 break;
218 }
219 case NetlinkEvent::Action::kChange: {
220 LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
221 handleDiskChanged(device);
222 break;
223 }
224 case NetlinkEvent::Action::kRemove: {
225 handleDiskRemoved(device);
226 break;
227 }
228 default: {
229 LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
230 break;
231 }
232 }
233 }
当一个外部存储插入设备后经过上报及区分后,调用handleDiskAdded函数
235 void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
236 // For security reasons, if secure keyguard is showing, wait
237 // until the user unlocks the device to actually touch it
238 if (mSecureKeyguardShowing) {
239 LOG(INFO) << "Found disk at " << disk->getEventPath()
240 << " but delaying scan due to secure keyguard";
241 mPendingDisks.push_back(disk);
242 } else {
//disk进行初始化,disk基础信息,分区挂载等
243 disk->create();
244 mDisks.push_back(disk);
245 }
246 }
disk→create()
155 status_t Disk::create() {
156 CHECK(!mCreated);
157 mCreated = true;
158 //从这里将会调用frameworks层StorageManagerService中的实现函数
159 auto listener = VolumeManager::Instance()->getListener();
160 if (listener) listener->onDiskCreated(getId(), mFlags);
161 //检查disk文件系统格式
162 readMetadata();
//读取分区列表
163 readPartitions();
164 return OK;
165 }
166
readPartitions()
status_t Disk::readPartitions() {
int maxMinors = getMaxMinors();
if (maxMinors < 0) {
return -ENOTSUP;
}
destroyAllVolumes();
// Parse partition table
//......
if (table == Table::kMbr) {
if (++it == split.end()) continue;
int type = 0;
if (!android::base::ParseInt("0x" + *it, &type)) {
LOG(WARNING) << "Invalid partition type " << *it;
continue;
}
switch (type) {
case 0x06: // FAT16
case 0x07: // HPFS/NTFS/exFAT
case 0x0b: // W95 FAT32 (LBA)
case 0x0c: // W95 FAT32 (LBA)
case 0x0e: // W95 FAT16 (LBA)
//挂载磁盘分区
createPublicVolume(partDevice);
break;
}
} else if (table == Table::kGpt) {
if (++it == split.end()) continue;
auto typeGuid = *it;
if (++it == split.end()) continue;
auto partGuid = *it;
if (android::base::EqualsIgnoreCase(typeGuid, kGptBasicData)) {
createPublicVolume(partDevice);
} else if (android::base::EqualsIgnoreCase(typeGuid, kGptAndroidExpand)) {
createPrivateVolume(partDevice, partGuid);
}
}
//......
}
createPublicVolume
178 void Disk::createPublicVolume(dev_t device) {
179 auto vol = std::shared_ptr<VolumeBase>(new PublicVolume(device));
180 if (mJustPartitioned) {
181 LOG(DEBUG) << "Device just partitioned; silently formatting";
182 vol->setSilent(true);
183 vol->create();
184 vol->format("auto");
185 vol->destroy();
186 vol->setSilent(false);
187 }
188
189 mVolumes.push_back(vol);
190 vol->setDiskId(getId());
//分区初始化,调用VolumeBase的create方法,由于PublicVolume是VolumeBase的子类,且具体实现VolumeBase的方法,这里其实调用的是PublicVolume的doCreate方法.
191 vol->create();
192 }
193
vol->create()
status_t VolumeBase::create() {
CHECK(!mCreated);
mCreated = true;
status_t res = doCreate();
auto listener = getListener();
//onVolumeCreated,通过binder机制,通知StorageManagerService创建volume,这里将会回调至frameworks层StorageManagerService中的实现函数
if (listener) listener->onVolumeCreated(getId(),
static_cast<int32_t>(mType), mDiskId, mPartGuid);
//设置状态
setState(State::kUnmounted);
return res;
}
void VolumeBase::setState(State state) {
mState = state;
auto listener = getListener();
//这里将会回调至frameworks层StorageManagerService中的实现函数,当分区初始化完成后,frameworks会发送mount广播。
if (listener) listener->onVolumeStateChanged(getId(), static_cast<int32_t>(mState));
}
StorageManagerService
1056 public void onVolumeCreated(String volId, int type, String diskId, String partGuid) {
1057 synchronized (mLock) {
1058 final DiskInfo disk = mDisks.get(diskId);
1059 final VolumeInfo vol = new VolumeInfo(volId, type, disk, partGuid);
1060 mVolumes.put(volId, vol);
1061 onVolumeCreatedLocked(vol);
1062 }
1063 }
1064
这里主要根据设备类型,设置挂载的Flag,最终通过handler发送挂载信息.
1145 @GuardedBy("mLock")
1146 private void onVolumeCreatedLocked(VolumeInfo vol) {
1147 if (mPms.isOnlyCoreApps()) {
1148 Slog.d(TAG, "System booted in core-only mode; ignoring volume " + vol.getId());
1149 return;
1150 }
1151
1152 if (vol.type == VolumeInfo.TYPE_EMULATED) {
1153 final StorageManager storage = mContext.getSystemService(StorageManager.class);
1154 final VolumeInfo privateVol = storage.findPrivateForEmulated(vol);
1155
1156 if (Objects.equals(StorageManager.UUID_PRIVATE_INTERNAL, mPrimaryStorageUuid)
1157 && VolumeInfo.ID_PRIVATE_INTERNAL.equals(privateVol.id)) {
1158 Slog.v(TAG, "Found primary storage at " + vol);
1159 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1160 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1161 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1162
1163 } else if (Objects.equals(privateVol.fsUuid, mPrimaryStorageUuid)) {
1164 Slog.v(TAG, "Found primary storage at " + vol);
1165 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1166 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1167 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1168 }
1169
1170 } else if (vol.type == VolumeInfo.TYPE_PUBLIC) {
1171 // TODO: only look at first public partition
1172 if (Objects.equals(StorageManager.UUID_PRIMARY_PHYSICAL, mPrimaryStorageUuid)
1173 && vol.disk.isDefaultPrimary()) {
1174 Slog.v(TAG, "Found primary storage at " + vol);
1175 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_PRIMARY;
1176 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1177 }
1178
1179 // Adoptable public disks are visible to apps, since they meet
1180 // public API requirement of being in a stable location.
1181 if (vol.disk.isAdoptable()) {
1182 vol.mountFlags |= VolumeInfo.MOUNT_FLAG_VISIBLE;
1183 }
1184
1185 vol.mountUserId = mCurrentUserId;
1186 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1187
1188 } else if (vol.type == VolumeInfo.TYPE_PRIVATE) {
1189 mHandler.obtainMessage(H_VOLUME_MOUNT, vol).sendToTarget();
1190
1191 } else {
1192 Slog.d(TAG, "Skipping automatic mounting of " + vol);
1193 }
1194 }
StorageManagerServiceHandler 发送挂载命令
559 class StorageManagerServiceHandler extends Handler {
560 public StorageManagerServiceHandler(Looper looper) {
561 super(looper);
562 }
563
564 @Override
565 public void handleMessage(Message msg) {
566 switch (msg.what) {
567 ......
614 case H_VOLUME_MOUNT: {
615 final VolumeInfo vol = (VolumeInfo) msg.obj;
616 if (isMountDisallowed(vol)) {
617 Slog.i(TAG, "Ignoring mount " + vol.getId() + " due to policy");
618 break;
619 }
620 try {
//发送挂载命令
621 mVold.mount(vol.id, vol.mountFlags, vol.mountUserId);
622 } catch (Exception e) {
623 Slog.wtf(TAG, e);
624 }
625 break;
626 }
627 case H_VOLUME_UNMOUNT: {
628 final VolumeInfo vol = (VolumeInfo) msg.obj;
629 unmount(vol.getId());
630 break;
631 }
632 case H_VOLUME_BROADCAST: {
633 final StorageVolume userVol = (StorageVolume) msg.obj;
634 final String envState = userVol.getState();
635 Slog.d(TAG, "Volume " + userVol.getId() + " broadcasting " + envState + " to "
636 + userVol.getOwner());
637
638 final String action = VolumeInfo.getBroadcastForEnvironment(envState);
639 if (action != null) {
640 final Intent intent = new Intent(action,
641 Uri.fromFile(userVol.getPathFile()));
642 intent.putExtra(StorageVolume.EXTRA_STORAGE_VOLUME, userVol);
643 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT
644 | Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
645 mContext.sendBroadcastAsUser(intent, userVol.getOwner());
646 }
647 break;
648 }
mVold.mount在VoldNativeService中处理
313 binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
314 int32_t mountUserId) {
315 ENFORCE_UID(AID_SYSTEM);
316 CHECK_ARGUMENT_ID(volId);
317 ACQUIRE_LOCK;
318
319 auto vol = VolumeManager::Instance()->findVolume(volId);
320 if (vol == nullptr) {
321 return error("Failed to find volume " + volId);
322 }
323
324 vol->setMountFlags(mountFlags);
325 vol->setMountUserId(mountUserId);
326 //调用VolumeBase的mount
327 int res = vol->mount();
328 if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
329 VolumeManager::Instance()->setPrimary(vol);
330 }
331 return translate(res);
332 }
//调用VolumeBase的mount
205 status_t VolumeBase::mount() {
206 if ((mState != State::kUnmounted) && (mState != State::kUnmountable)) {
207 LOG(WARNING) << getId() << " mount requires state unmounted or unmountable";
208 return -EBUSY;
209 }
210 //设置当前状态为checking
211 setState(State::kChecking);
//调用子类PublicVolume的doMount方法.
212 status_t res = doMount();
213 if (res == OK) {
//设置挂载成功状态,向上通知onVolumeStateChanged.
214 setState(State::kMounted);
215 } else {
216 setState(State::kUnmountable);
217 }
218
219 return res;
220 }
//实现挂载,主要是根据文件系统类型调用相应的mount函数,最后完成FUSE文件系统的挂载,从而实现用户访问文件系统的需求
96 status_t PublicVolume::doMount() {
97 readMetadata();
98
99 if (mFsType == "vfat" && vfat::IsSupported()) {
100 if (vfat::Check(mDevPath)) {
101 LOG(ERROR) << getId() << " failed filesystem check";
102 return -EIO;
103 }
104 } else if (mFsType == "exfat" && exfat::IsSupported()) {
105 if (exfat::Check(mDevPath)) {
106 LOG(ERROR) << getId() << " failed filesystem check";
107 return -EIO;
108 }
109 } else {
110 LOG(ERROR) << getId() << " unsupported filesystem " << mFsType;
111 return -EIO;
112 }
113
114 // Use UUID as stable name, if available
115 std::string stableName = getId();
116 if (!mFsUuid.empty()) {
117 stableName = mFsUuid;
118 }
119
120 mRawPath = StringPrintf("/mnt/media_rw/%s", stableName.c_str());
121
122 mFuseDefault = StringPrintf("/mnt/runtime/default/%s", stableName.c_str());
123 mFuseRead = StringPrintf("/mnt/runtime/read/%s", stableName.c_str());
124 mFuseWrite = StringPrintf("/mnt/runtime/write/%s", stableName.c_str());
125
126 setInternalPath(mRawPath);
127 if (getMountFlags() & MountFlags::kVisible) {
128 setPath(StringPrintf("/storage/%s", stableName.c_str()));
129 } else {
130 setPath(mRawPath);
131 }
132
133 if (fs_prepare_dir(mRawPath.c_str(), 0700, AID_ROOT, AID_ROOT)) {
134 PLOG(ERROR) << getId() << " failed to create mount points";
135 return -errno;
136 }
137
138 if (mFsType == "vfat") {
139 if (vfat::Mount(mDevPath, mRawPath, false, false, false, AID_MEDIA_RW, AID_MEDIA_RW, 0007,
140 true)) {
141 PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
142 return -EIO;
143 }
144 } else if (mFsType == "exfat") {
145 if (exfat::Mount(mDevPath, mRawPath, AID_MEDIA_RW, AID_MEDIA_RW, 0007)) {
146 PLOG(ERROR) << getId() << " failed to mount " << mDevPath;
147 return -EIO;
148 }
149 }
150
151 if (getMountFlags() & MountFlags::kPrimary) {
152 initAsecStage();
153 }
154
155 if (!(getMountFlags() & MountFlags::kVisible)) {
156 // Not visible to apps, so no need to spin up FUSE
157 return OK;
158 }
159
160 if (fs_prepare_dir(mFuseDefault.c_str(), 0700, AID_ROOT, AID_ROOT) ||
161 fs_prepare_dir(mFuseRead.c_str(), 0700, AID_ROOT, AID_ROOT) ||
162 fs_prepare_dir(mFuseWrite.c_str(), 0700, AID_ROOT, AID_ROOT)) {
163 PLOG(ERROR) << getId() << " failed to create FUSE mount points";
164 return -errno;
165 }
166
167 dev_t before = GetDevice(mFuseWrite);
168
169 if (!(mFusePid = fork())) {
170 if (getMountFlags() & MountFlags::kPrimary) {
171 if (execl(kFusePath, kFusePath,
172 "-u", "1023", // AID_MEDIA_RW
173 "-g", "1023", // AID_MEDIA_RW
174 "-U", std::to_string(getMountUserId()).c_str(),
175 "-w",
176 mRawPath.c_str(),
177 stableName.c_str(),
178 NULL)) {
179 PLOG(ERROR) << "Failed to exec";
180 }
181 } else {
182 if (execl(kFusePath, kFusePath,
183 "-u", "1023", // AID_MEDIA_RW
184 "-g", "1023", // AID_MEDIA_RW
185 "-U", std::to_string(getMountUserId()).c_str(),
186 mRawPath.c_str(),
187 stableName.c_str(),
188 NULL)) {
189 PLOG(ERROR) << "Failed to exec";
190 }
191 }
192
193 LOG(ERROR) << "FUSE exiting";
194 _exit(1);
195 }
196
197 if (mFusePid == -1) {
198 PLOG(ERROR) << getId() << " failed to fork";
199 return -errno;
200 }
201
202 nsecs_t start = systemTime(SYSTEM_TIME_BOOTTIME);
203 while (before == GetDevice(mFuseWrite)) {
204 LOG(VERBOSE) << "Waiting for FUSE to spin up...";
205 usleep(50000); // 50ms
206
207 nsecs_t now = systemTime(SYSTEM_TIME_BOOTTIME);
208 if (nanoseconds_to_milliseconds(now - start) > 5000) {
209 LOG(WARNING) << "Timed out while waiting for FUSE to spin up";
210 return -ETIMEDOUT;
211 }
212 }
213 /* sdcardfs will have exited already. FUSE will still be running */
214 if (TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, WNOHANG)) == mFusePid)
215 mFusePid = 0;
216
217 return OK;
218 }
以上即是vold进程对于外部存储设备的大致加载过程。监听kennel事件先创建disk,然后再挂载volume。这里需要注意内置的存储没有disk,只有volume。
PS:整个U盘的挂载一般要经历这么几个阶段
- sgdisk 创建分区
- mke2fs 格式化文件系统
- e2fsck 检查文件系统的正确性
- blkid 检查sdcard是什么格式的