按照android文档,Android 4.3 及更高版本,init、vold和recovery所用到的都是/fstab.<device>
文件。但是在AndroidO 的中,似乎发生了变化。
在fsmgr
中,fstab 的来源有两个,一个是device tree
中指定,另一个则是从fstab.<device>
文件中加载。这两个来源的中的fstab配置最终会被合并到一起。
fstab 文件
可以看出,AndroidO中配置 fstab
文件的地方有三个: /odm/etc/
、/vendor/etc/
和/
,优先级由大变小。
fstab.
中的 device 值就是属性 ro.boot.hardware 的值,如果没有配置该属性,就会去/proc/cmdline中读取hardware的值,还读不到就去查找 device tree。
在Rockchip平台上,fstab.rk30board直接保存到了根目录。不太清楚为啥不按照安卓标准,放在
/vendor/etc
目录下面额。
设备树中的配置
通过查看RK339的设备树文件,可以看到system
和vendor
分区的配置是在设备树中配置的。
fstab的基本格式如下:
<src> <mnt_point> <type> <mnt_flags> <fs_mgr_flags>
src
: sysfs(/sys
)下可以的设备的路径。路径必须以/
开头,设备的实际路径是/sys$(src)
。mnt_point
: 设备挂载路径。type
: 该设备的上的卷的文件类型。mnt_flags
:Vold会忽略该字段,所以,对于由vold管理的设备,该字段可以设置为defaults
fs_mgr_flags
:fs_mgr_flags
:Vold
会忽略此字段中不包含 voldmanaged=
标记的统一的 fstab 中的任何行。该标记必须后跟描述卡的标签,以及分区号或字词 auto
。例如:voldmanaged=sdcard:auto
。fs_msg中,使用 struct fstab
来表示fstab文件中的数据,使用struct fstab_rec
来表示fstab中的每一条记录。
struct fstab {
int num_entries; // fstab中的记录数
struct fstab_rec* recs; // fstab中的所有条目
char* fstab_filename; // fstab的文件路径
};
struct fstab_rec {
char* blk_device; // 对一个 <src>
char* mount_point; // 对应 <mnt_point>
char* fs_type; // 对应 <type>
unsigned long flags; // 对应 <mnt_flags>
char* fs_options; // <mnt_flags>中未记录在struct flag_list mount_flags中的字段
int fs_mgr_flags; // 对应 <fs_mgr_flags>
// -----------------------------------------------------
char* key_loc;
char* key_dir;
char* verity_loc;
long long length; // length=
char* label; // voldmanaged=sdcard:3 label=sdcard
int partnum; // voldmanaged=sdcard:3 partnum = 3 auto partnum = 1
int swap_prio; // swapprio=
int max_comp_streams;
unsigned int zram_size;
uint64_t reserved_size;
unsigned int file_contents_mode;
unsigned int file_names_mode;
unsigned int erase_blk_size;
unsigned int logical_blk_size;
};
struct fstab_rec
的前6个,就分别对应fstab中记录项。后面的就是记录fs_mgr_flags
中的参数的值。
struct fstab_rec->fs_options
比较特殊,其记录的是mnt_flags
中,未记录的参数类型。当执行mount的时候,他将直接作为参数传递过去。static struct flag_list mount_flags[] = { { "noatime", MS_NOATIME }, { "noexec", MS_NOEXEC }, { "nosuid", MS_NOSUID }, { "nodev", MS_NODEV }, { "nodiratime", MS_NODIRATIME }, { "ro", MS_RDONLY }, { "rw", 0 }, { "remount", MS_REMOUNT }, { "bind", MS_BIND }, { "rec", MS_REC }, { "unbindable", MS_UNBINDABLE }, { "private", MS_PRIVATE }, { "slave", MS_SLAVE }, { "shared", MS_SHARED }, { "defaults", 0 }, { 0, 0 }, };
实际解析过程就是逐行解析,然后分割字符串。没啥好记录的,代码太长就不贴了。可以看一下解析函数:
static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file) {
// [1] 统计行数
// [2] 分配 fstab 内存和 fstab_rec 内存
// [3] 逐行解析
}
内核DTS中的配置,最终都会在目录/proc/device-tree
下体现,android也有一些自有配置,其目录是/proc/device-tree/firmware/android
。其中fstab就记录在该目录下(完整目录就是/proc/device-tree/firmware/android/fstab
)。
结合前面的 DTS截图,最终fstab生成的目录结构如下:
/proc/device-tree/firmware/android/fstab/
system
status
dev
type
mnt_flags
fsmgr_flags
vendor
status
dev
type
mnt_flags
fsmgr_flags
fs_mgr对其的解析过程就是遍历/proc/device-tree/firmware/android/fstab/
,一次读取其每个子目录的所有节点数据,每个目录构建成一个<dev> <mnt_point> <type> <mnt_flags> <fsmgr_flags>\n
形式的字符串。然后拼接。
? 最后,将read_fstab_from_dt
返回的字符串转换成FILE*
调用函数fs_mgr_read_fstab_file
完成解析。
前面提到fs_mgr会将fstab文件和DTS中的配置信息合并。合并过程也很简单,就是创建一片内存,将两个部分的数据拷贝过去。
如果 fstab文件和 DTS 中的 配置项存在重复,fs_mgr 是怎么处理。
原文:https://www.cnblogs.com/liutimo/p/14032429.html