0
点赞
收藏
分享

微信扫一扫

Android9.0 vold初始化及外部存储器挂载浅析

一、概况

在Android 中,当SD卡U盘等外部存储器插入系统之后,系统会自动挂载。Vold 就是负责挂载的,vold 的全称是volume daemon。实际上是负责完成系统的CDROM,USB 大容量存储,MMC 卡等扩展存储的挂载任务自动完成的守护进程。它提供的主要特点是支持这些存储外设的热插拔。

Android9.0 vold初始化及外部存储器挂载浅析_初始化

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是什么格式的

Android9.0 vold初始化及外部存储器挂载浅析_android_02

举报

相关推荐

0 条评论