Android 分区挂载 -- Fstab 文件

Fstab 文件是一个静态文件,用于定义如何将磁盘分区、各种其他块设备或者远程文件系统挂载到文件系统中。

通常 Linux 内核操作系统中,Fstab 文件路径为:/etc/fstab,我们可以使用 more 或者 less 命令查看,使用 vi 命令进行编辑。Android 手机文件存放路径与Linux 操作系统有些许差异,以 MTK 平台手机为例:

  • 源码中 fstab 文件路径为:alps/vendor/mediatek/proprietary/hardware/fstab/mtxxxx/fstab.in.mtxxxx

  • 机器中 fstab 文件路径为:/vendor/etc/fstab.mtxxxx

源码 fstab 文件根据不同的编译选项以及标签生成 Android 系统中的 fstab 文件。

文件示例:

# fstab.in.mt6781
##############################################################################################################################
# <src>             <mount point>     <type>                 <<mount flags parameters>>      <FsMgr Flags >
#ifdef __VENDOR_PARTITION_SUPPORT
LP_DEVPATH(vendor)  /vendor           __MTK_VNDIMG_FSTYPE    ro                              FSMGR_FLAG_VENDOR
#endif
DEVPATH(rescue)     /cache            ext4                   FS_FLAG_DISCARD                 FSMGR_FLAG_FMT

# fstab.mt6781
#############################################################################################################################

# 1 "vendor/mediatek/proprietary/hardware/fstab/mt6781/fstab.in.mt6781"
# <src>    <mount point>      <filesystem type>     <fs option>
vendor     /vendor            ext4                  ro wait,slotselect,avb,logical,first_stage_mount
/dev/block/platform/bootdevice/by-name/rescue /cache ext4 noatime,nosuid,nodev,noauto_da_alloc,discard wait,check,formattable

Fstab 字段说明

  • src :待挂载的分区或者存储设备。

  • mount point :挂载点,<src> 挂载的目标路径。

  • type :要挂载的分区或者设备的文件系统类型。如 Ext4vFatswapswapNTFSexFATauto 等,设置成auto类型,mount 命令会自动判定挂载的文件系统类型,对 CDROM 和 DVD 等移动设备是非常有用的。

  • fs option :文件系统挂载选项,部分选项是特定文件系统才具有的。常用的挂载选项如下:

    • noatime: 禁用对文件和目录的访问时间(atime)的更新,以此提升访问效率。

      atime:不使用 noatime 功能,因此 iNode 访问时间由内核默认值控制,即每次访问文件都需要更新 atime。

    • noexec:禁止在此文件系统上执行二进制文件。

      exec:允许在此文件系统上执行二进制文件。

    • nosuid:禁止 suid 操作和设定 sgid 位。

      suid:允许 suid 操作和设定 sgid 位。这一参数通常用于一些特殊任务,使一般用户运行程序时临时提升权限。

    • nodev: 启用 nodev 后,挂载的文件系统不会识别或处理任何设备文件(如字符设备 /dev/null 或块设备 /dev/sda)。

      dev:解析文件系统上的字符或块特殊设备。

    • nodiratime: 禁用对目录的访问时间(atime)的更新。通常情况下,每次访问目录时,文件系统都会更新该目录的访问时间戳,这会导致额外的写操作,从而影响性能。启用 nodiratime 选项后,文件系统将不再更新目录的访问时间戳,从而减少写操作,提高性能。这个选项特别适用于那些频繁访问目录但不需要记录访问时间的场景。

    • ro:以只读方式挂载文件系统。

    • rw:以读写方式挂载文件系统。

    • sync: IO 同步进行

      async:IO 异步进行。

    • barrier=1: 用于确保数据的完整性。barrier 功能(Write Barrier)会在写入新的数据块到磁盘之前,先将元数据写入日志。这可以防止在写入真实数据前后发生错误(例如突然断电),从而确保文件系统的安全性和一致性。启用 barrier 功能(即 barrier=1)会强制元数据先于数据落盘,以保证磁盘数据的一致性。虽然这可能会对性能产生一些影响,但它可以有效防止文件系统崩溃。

    • nobarrier: 禁用 barrier 功能,可以减少磁盘同步等待,从而提高系统性能,但会增加数据损坏风险。

    • remount: 支持重新挂载已挂载的文件系统。

    • bind: 将一个目录绑定到另一个目录。

    • rec: 用于递归地挂载文件系统。这意味着,如果您在挂载点下有子目录或子文件系统,它们也会被递归地挂载。

    • unbindable: 用于防止挂载点被绑定到其他位置。当一个挂载点被标记为 unbindable 时,它不能被 mount --bind 命令绑定到另一个位置。这对于确保某些挂载点的安全性和隔离性非常有用。

    • private: 用于确保挂载点的隔离性。当一个挂载点被标记为 private 时,任何在该挂载点上进行的挂载或卸载操作都不会传播到其他挂载点。这对于确保某些挂载点的安全性和隔离性非常有用。

    • slave: 用于控制 挂载传播(Mount Propagation) 的行为。它属于 Linux 内核的挂载命名空间(Mount Namespace)功能,常见于容器化技术(如 Docker)或需要隔离文件系统挂载的场景。

    • shared: 用于控制 挂载传播(Mount Propagation) 的行为。它允许挂载事件在多个挂载点之间双向同步,属于 Linux 内核挂载命名空间(Mount Namespace)功能的一部分,常见于需要共享文件系统状态的场景(如容器、共享存储等)。

    • defaults:使用默认选项:rw、suid、dev、exec、auto、nouser 和 async。注意,所有默认挂载选项的真实集合取决于内核和文件系统类型。

  • FsMgr Flags:Android 10 引入以下可以在 fstab 文件中使用的 fs_mgr 标签。

    • wait:在启动过程中等待特定的设备准备好后再继续挂载操作。这个选项通常用于确保在挂载文件系统之前,设备已经完全初始化并可用。

    • check:在挂载前检查文件系统的完整性。

    • nonremoveable: 用于标记设备为不可移除设备。这意味着该设备在系统运行期间不会被移除或卸载。这个选项通常用于内部存储设备,以确保它们在系统启动和运行期间始终可用。

    • formattable: 允许格式化文件系统。

    • first_stage_mount:在启动过程的第一阶段挂载文件系统。

    • latemount:启动过程的第二阶段后期挂载文件系统,通常对应挂载命令为: mount_all --late

    • slotselect: 根据当前活动的插槽选择挂载设备。

    • fsverity: 启用文件系统完整性验证。

    • avb:启用 Android Verified Boot,即 Android 的验证启动机制,确保启动过程中每个分区的完整性和合法性。通过验证分区的哈希值或签名,防止恶意篡改。

      • 如果分区仅设置 avb,则默认使用 vbmeta 分区中的元数据进行验证。
      • 如果分区设置 avb=xxx,显式指定从配置分区加载元数据进行验证。例如:avb=vbmeta 显式指定从 vbmeta 分区加载元数据,与 avb 默认行为一致;avb=vbmeta_system 显式指定从 vbmeta_system 分区加载元数据验证。
    • avb_keys: 用于指定自定义验证密钥的挂载选项,允许覆盖默认的验证密钥或为特定分区配置独立的密钥。

    • nofail: 即使挂载失败也继续启动过程。

    • notrim: 禁用 TRIM 操作。

    • quota: 用于启用文件系统配额支持。配额允许管理员限制用户或组在文件系统上可以使用的磁盘空间和文件数量。

    • resize: resize 扩容功能,用于 userdata 分区。当 userdata 分区设置此标签后,未使用的存储空间会自动扩容给 userdata 分区。

    • reservedsize=xxx: 用于指定文件系统中保留的空间大小。这个选项通常用于确保系统在文件系统接近满载时仍有足够的空间进行关键操作,例如日志记录、系统更新等,防止普通用户占用这些空间,从而确保系统在文件系统接近满载时仍能正常运行。

    • checkpoint=block: 启用块级检查点。

    • checkpoint=fs:启用文件系统级检查点。

    • fileencryption: 配置 FBE(File-Based Encryption:基于文件的加密)。

      fileencryption 选项的格式为 fileencryption=contents_encryption_mode[:filenames_encryption_mode[:flags]]

      例如 userdata 分区:fileencryption=aes-256-xts:aes-256-cts:v2

    • keydirectory: 用于指定存储加密密钥的目录路径。系统会从该目录中加载加密密钥,用于解密和加密文件系统中的数据。这个选项通常用于基于文件的加密(File-Based Encryption,FBE)或其他需要密钥管理的场景。

    • metadata_encryption: 启用元数据加密。元数据加密(Metadata Encryption)用于保护文件系统的元数据,包括目录结构、文件名、权限、时间戳等信息。启用元数据加密可以提高系统的安全性,防止未经授权的访问和篡改。

Android 分区挂载大致分为两个时机,分别是 init 启动过程中的第一阶段和第二阶段。

  • init 启动第一阶段(FirstStageMain)。该阶段主要挂载带有 first_stage_mount fs_mgr 标签的分区。例如 metadatasystemvendor 等分区。

    int FirstStageMain(int argc, char** argv) {
         ...
         if (IsRecoveryMode()) {
             LOG(INFO) << "First stage mount skipped (recovery mode)";
         } else {
             if (!fsm) {
                 fsm = CreateFirstStageMount(cmdline);
             }
             if (!fsm) {
                 LOG(FATAL) << "FirstStageMount not available";
             }
     
             if (!created_devices && !fsm->DoCreateDevices()) {
                 LOG(FATAL) << "Failed to create devices required for first stage mount";
             }
     
             if (!fsm->DoFirstStageMount()) {
                 LOG(FATAL) << "Failed to mount required partitions early ...";
             }
         }
         ...
    }
    
  • init 启动第二阶段(SecondStageMain)。该阶段会解析 rc 并加载执行 rc 文件。分区挂载行为通过 rc 文件触发并调用 mount_all 命令进行挂载。分别在 fslate-fs 阶段挂载第一阶段未挂载的分区。

    • –early:挂载不带 first_stage_mountlatemount 标签的分区。
    • –late:挂载带有 latemount 标签的分区。
    int SecondStageMain(int argc, char** argv) {
    	...
    	LoadBootScripts(am, sm);  /* 解析 rc 文件 */
    	...
    	am.QueueEventTrigger("early-init");
    	...
    	am.QueueEventTrigger("init");
    	...
    	if (bootmode == "charger") {
    		am.QueueEventTrigger("charger");
    	} else {
    		am.QueueEventTrigger("late-init");
    	}
        ...
    }
    
    # init.rc
    on late-init
        trigger early-fs
    
        # Mount fstab in init.{$device}.rc by mount_all command. Optional parameter
        # '--early' can be specified to skip entries with 'latemount'.
        # /system and /vendor must be mounted by the end of the fs stage,
        # while /data is optional.
        trigger fs
        trigger post-fs
    
        # Mount fstab in init.{$device}.rc by mount_all with '--late' parameter
        # to only mount entries with 'latemount'. This is needed if '--early' is
        # specified in the previous mount_all command on the fs stage.
        # With /system mounted and properties form /system + /factory available,
        # some services can be started.
        trigger late-fs
    
    ################################################################################
    
    # platform .rc 
    
    ################################################################################
    # mtk platform
    ################################################################################
    on fs
        mount_all /vendor/etc/fstab.${ro.hardware} --early
    
    on late-fs
        # Mount RW partitions which need run fsck
        mount_all /vendor/etc/fstab.${ro.hardware} --late
        
    ################################################################################
    # qcom platform
    ################################################################################
    on fs
        mount_all --early
    
    on late-fs
    	mount_all --late
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值