安卓挂载文件系统流程
1、init进程
system/core/init/man.cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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
1 2 3 4 5 6 | int SecondStageMain( int argc, char ** argv) { ...... //加载开机脚本init.rc LoadBootScripts(am, sm); ...... } |
解析脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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
1 2 3 4 5 | { "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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | 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阶段挂载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | #<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 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库