安卓挂载文件系统流程
1、init进程
system/core/init/man.cpp
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#endif
// Boost prio which will be restored later
setpriority(PRIO_PROCESS, 0, -20);
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
//权限相关
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
//第二阶段
return SecondStageMain(argc, argv);
}
}
//第一阶段
return FirstStageMain(argc, argv);
}
2、加载开机脚本init.rc
/system/core/init/init.cpp
int SecondStageMain(int argc, char** argv) {
......
//加载开机脚本init.rc
LoadBootScripts(am, sm);
......
}
解析脚本:
static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
Parser parser = CreateParser(action_manager, service_list);
std::string bootscript = GetProperty("ro.boot.init_rc", "");
if (bootscript.empty()) {
parser.ParseConfig("/system/etc/init/hw/init.rc");
if (!parser.ParseConfig("/system/etc/init")) {
late_import_paths.emplace_back("/system/etc/init");
}
// late_import is available only in Q and earlier release. As we don't
// have system_ext in those versions, skip late_import for system_ext.
parser.ParseConfig("/system_ext/etc/init");
if (!parser.ParseConfig("/vendor/etc/init")) {
late_import_paths.emplace_back("/vendor/etc/init");
}
if (!parser.ParseConfig("/odm/etc/init")) {
late_import_paths.emplace_back("/odm/etc/init");
}
if (!parser.ParseConfig("/product/etc/init")) {
late_import_paths.emplace_back("/product/etc/init");
}
} else {
parser.ParseConfig(bootscript);
}
}
3、mount_all去挂载分区mount的阶段分为mount_all --early和mount_all --late
/device/qcom/sc171/init.target.rc
on fs
start hwservicemanager
mkdir /mnt/vendor/spunvm 0660 system system
mount_all --early
chown root system /mnt/vendor/persist
chmod 0771 /mnt/vendor/persist
restorecon_recursive /mnt/vendor/persist
mkdir /mnt/vendor/persist/data 0700 system system
on fs && property:ro.boot.product.vendor.sku=lahaina
mkdir /mnt/vendor/spunvm 0660 system system
wait /dev/block/bootdevice/by-name/spunvm
mount vfat /dev/block/bootdevice/by-name/spunvm /mnt/vendor/spunvm rw noatime shortname=lower,uid=1000,gid=1000,dmask=007,fmask=007,context=u:object_r:vendor_spunvm_file:s0
on post-fs
# set RLIMIT_MEMLOCK to 64MB
setrlimit 8 67108864 67108864
on late-fs
wait_for_prop hwservicemanager.ready true
#exec_start wait_for_keymaster
mount_all --late
/system/core/init/buildins.cpp
{"mount_all", {0, kMax, {false, do_mount_all}}},
{"mount", {3, kMax, {false, do_mount}}},
{"perform_apex_config", {0, 0, {false, do_perform_apex_config}}},
{"umount", {1, 1, {false, do_umount}}},
{"umount_all", {0, 1, {false, do_umount_all}}},
调用do_mount_all
static Result<void> do_mount_all(const BuiltinArguments& args) {
auto mount_all = ParseMountAll(args.args);
if (!mount_all.ok()) return mount_all.error();
const char* prop_post_fix = "default";
bool queue_event = true;
if (mount_all->mode == MOUNT_MODE_EARLY) {
prop_post_fix = "early";
queue_event = false;
} else if (mount_all->mode == MOUNT_MODE_LATE) {
prop_post_fix = "late"
}
std::string prop_name = "ro.boottime.init.mount_all."s + prop_post_fix;
android::base::Timer t;
Fstab fstab;
if (mount_all->fstab_path.empty()) {
if (!ReadDefaultFstab(&fstab)) {
return Error() << "Could not read default fstab";
}
} else {
if (!ReadFstabFromFile(mount_all->fstab_path, &fstab)) {
return Error() << "Could not read fstab";
}
}
//mount所有分区
auto mount_fstab_result = fs_mgr_mount_all(&fstab, mount_all->mode);
SetProperty(prop_name, std::to_string(t.duration().count()));
4、调用fs_mgr_mount_all回去解析fstab.default文件去挂载相应的分区
/system/core/fs_mgr/fs_mgr.cpp
fstab.defalut---/device/qcom/sc171/default/fstab.default
5、mount_all --early和mount_all --late
分区是在early的阶段挂载还是在late取决于fstab.default中对于每个分区fs_mgr_flags中first_stage_mount和latemount属性的配置,
- 如果配置了first_stage_mount则在early的阶段进行挂载
- 配置了latemount则在late阶段挂载
#<src> <mnt_point> <type> <mnt_flags and options> <fs_mgr_flags>
system /system ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount,avb_keys=/avb/q-gsi.avbpubkey:/avb/r-gsi.avbpubkey:/avb/s-gsi.avbpubkey
system_ext /system_ext ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount
product /product ext4 ro,barrier=1,discard wait,slotselect,avb=vbmeta_system,logical,first_stage_mount
vendor /vendor ext4 ro,barrier=1,discard wait,slotselect,avb,logical,first_stage_mount
odm /odm ext4 ro,barrier=1,discard wait,slotselect,avb,logical,first_stage_mount
/dev/block/by-name/metadata /metadata ext4 noatime,nosuid,nodev,discard wait,check,formattable,first_stage_mount
/dev/block/bootdevice/by-name/persist /mnt/vendor/persist ext4 noatime,nosuid,nodev,barrier=1 wait
/dev/block/bootdevice/by-name/userdata /data ext4 noatime,nosuid,nodev,barrier=1,noauto_da_alloc,discard latemount,wait,formattable,encryptable=footer,quota,reservedsize=128M
/dev/block/bootdevice/by-name/misc /misc emmc defaults defaults
/devices/platform/soc/8804000.sdhci/mmc_host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=footer
/devices/platform/soc/1da4000.ufshc_card/host* /storage/sdcard1 vfat nosuid,nodev wait,voldmanaged=sdcard1:auto,encryptable=footer
/*.ssusb/*.dwc3/xhci-hcd.*.auto* /storage/usbotg vfat nosuid,nodev wait,voldmanaged=usbotg:auto
/devices/platform/soc/*.hsusb/*.dwc3/xhci-hcd.*.auto* /storage/usbotg vfat nosuid,nodev wait,voldmanaged=usbotg:auto
/dev/block/bootdevice/by-name/modem /vendor/firmware_mnt vfat ro,shortname=lower,uid=1000,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0 wait,slotselect
/dev/block/bootdevice/by-name/dsp /vendor/dsp ext4 ro,nosuid,nodev,barrier=1 wait,slotselect
/dev/block/bootdevice/by-name/bluetooth /vendor/bt_firmware vfat ro,shortname=lower,uid=1002,gid=3002,dmask=227,fmask=337,context=u:object_r:bt_firmware_file:s0 wait,slotselect
/dev/block/bootdevice/by-name/qmcs /mnt/vendor/qmcs vfat noatime,nosuid,nodev,context=u:object_r:vendor_qmcs_file:s0 wait,check,formattable
/dev/block/bootdevice/by-name/data2 /mnt/data2 ext4 discard latemount
/dev/block/bootdevice/by-name/data3 /mnt/data3 ext4 discard latemount