userdata.img里的block count等于userdata partition size/block_size
userdata.img里的block count等于userdata partition size/block_size
build/core/Makefile
define build-userdataimage-target $(call pretty,"Target userdata fs image: $(INSTALLED_USERDATAIMAGE_TARGET)") @mkdir -p $(TARGET_OUT_DATA) @mkdir -p $(userdataimage_intermediates) && rm -rf $(userdataimage_intermediates)/userdata_image_info.txt $(call generate-image-prop-dictionary, $(userdataimage_intermediates)/userdata_image_info.txt,userdata,skip_fsck=true) $(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \ build/make/tools/releasetools/build_image.py \ $(TARGET_OUT_DATA) $(userdataimage_intermediates)/userdata_image_info.txt $(INSTALLED_USERDATAIMAGE_TARGET) $(TARGET_OUT)
TARGET_OUT_DATA is out/target/product/[device]/data
INSTALLED_USERDATAIMAGE_TARGET is out/target/product/$device/userdata.img
TARGET_OUT is out/target/product/$device/system
$(userdataimage_intermediates)/userdata_image_info.txt is:
out/target/product/[device]/obj/PACKAGING/userdata_intermediates/userdata_image_info.txt:
userdata_size=4625268736 ext_mkuserimg=mkuserimg_mke2fs fs_type=ext4 extfs_sparse_flag=-s squashfs_sparse_flag=-s selinux_fc=out/target/product/$(device)/obj/ETC/file_contexts.bin_intermediates/file_contexts.bin root_dir=out/target/product/$(device)/root use_dynamic_partition_size=true skip_fsck=true
build/tools/releasetools/build_image.py
def main(argv): in_dir = argv[0] glob_dict_file = argv[1] out_file = argv[2] target_out = argv[3] glob_dict = LoadGlobalDict(glob_dict_file) if "mount_point" in glob_dict: # The caller knows the mount point and provides a dictionary needed by # BuildImage(). image_properties = glob_dict else: image_filename = os.path.basename(out_file) mount_point = "" if image_filename == "system.img": mount_point = "system" elif image_filename == "system_other.img": mount_point = "system_other" elif image_filename == "userdata.img": mount_point = "data" elif image_filename == "cache.img": mount_point = "cache" elif image_filename == "vendor.img": mount_point = "vendor" elif image_filename == "odm.img": mount_point = "odm" elif image_filename == "oem.img": mount_point = "oem" elif image_filename == "product.img": mount_point = "product" elif image_filename == "product_services.img": mount_point = "product_services" else: logger.error("Unknown image file name %s", image_filename) sys.exit(1) image_properties = ImagePropFromGlobalDict(glob_dict, mount_point) try: BuildImage(in_dir, image_properties, out_file, target_out)
def ImagePropFromGlobalDict(glob_dict, mount_point): elif mount_point == "data": # Copy the generic fs type first, override with specific one if available. copy_prop("fs_type", "fs_type") copy_prop("userdata_fs_type", "fs_type") copy_prop("userdata_size", "partition_size") copy_prop("flash_logical_block_size", "flash_logical_block_size") copy_prop("flash_erase_block_size", "flash_erase_block_size")
在prop_dict里有了partition_size prop,即device/$vendor/$product/BoardConfig.mk里define的userdata partition size
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | def BuildImage(in_dir, prop_dict, out_file, target_out = None ): if (prop_dict.get( "use_dynamic_partition_size" ) = = "true" and "partition_size" not in prop_dict): / / not the case ... / / the case prop_dict[ "image_size" ] = prop_dict[ "partition_size" ] / / image_size即为userdata partition size definition mkfs_output = BuildImageMkfs(in_dir, prop_dict, out_file, target_out, fs_config) def BuildImageMkfs(in_dir, prop_dict, out_file, target_out, fs_config): if fs_type.startswith( "ext" ): build_command = [prop_dict[ "ext_mkuserimg" ]] / / ext_mkuserimg值为mkuserimg_mke2fs build_command.append(prop_dict[ "image_size" ]) if "extfs_inode_count" in prop_dict: / / 以userdata.img为例,它在userdata_image_info.txt里是没有define inode count的 build_command.extend([ "-i" , prop_dict[ "extfs_inode_count" ]]) build_command.extend([ "--inode_size" , "256" ]) if "selinux_fc" in prop_dict: build_command.append(prop_dict[ "selinux_fc" ]) / / 将执行ext_mkuserimg,即执行mkuserimg_mke2fs.py mkfs_output = common.RunAndCheckOutput(build_command) |
system\extras\ext4_utils\Mkuserimg_mke2fs.py
def main(argv): args = ParseArguments(argv) if args.mount_point[0] != '/': args.mount_point = '/' + args.mount_point if not args.fs_size: logging.error("Size of the filesystem is required") sys.exit(2) mke2fs_cmd, e2fsdroid_cmd = ConstructE2fsCommands(args)
def ParseArguments(argv): parser.add_argument("src_dir", help="The source directory for user image.") parser.add_argument("output_file", help="The path of the output image file.") parser.add_argument("ext_variant", choices=["ext2", "ext4"], help="Variant of the extended filesystem.") parser.add_argument("mount_point", help="The mount point for user image.") parser.add_argument("fs_size", help="Size of the file system.") //即userdata partition size definition parser.add_argument("--inodes", "-i", help="The extfs inodes count (mke2fs).") parser.add_argument("--inode_size", "-I", help="The extfs inode size (mke2fs).")
def ConstructE2fsCommands(args): BLOCKSIZE = 4096 if args.inodes: mke2fs_opts += ["-N", args.inodes] if args.inode_size: mke2fs_opts += ["-I", args.inode_size] if args.mount_point: mke2fs_opts += ["-M", args.mount_point] # Round down the filesystem length to be a multiple of the block size blocks = int(args.fs_size) / BLOCKSIZE mke2fs_cmd = (["mke2fs"] + mke2fs_opts + ["-t", args.ext_variant, "-b", str(BLOCKSIZE), args.output_file, str(blocks)]) e2fsdroid_cmd = (["e2fsdroid"] + e2fsdroid_opts + ["-f", args.src_dir, "-a", args.mount_point, args.output_file]) return mke2fs_cmd, e2fsdroid_cmd
上述mke2fs_cmd中的blocks是userdata partition size definition/block_size(所以会将其block size对齐,block size是4K),所以生成的userdata.img里是包含userdata partition size信息的,即block count
mke2fs、e2fsdroid是可执行程序,路径在out/host/linux-x86/bin
用dumpe2fs tool解析build出来的userdata.ext4查看block count为1129216,1129216 * 4096 = 4,625,268,736,和userdata partition size definition一致:
dumpe2fs -f userdata.ext4
Block count: 1129216
BOARD_USERDATAIMAGE_PARTITION_SIZE := 4625268736
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
2020-05-22 Android ANR log trace日志文件分析
2020-05-22 ANR分析思路简析
2020-05-22 ANR traces中内存占用情况解读