System.imgはどのようにパッケージ化されていますか?
18608 ワード
makeコマンドをタップすると、最初のターゲットdroid(build/core/main.mk)が見つかり、droidはdroidに依存します.targets,droid_targets依存droidcoreとdist_files,droidcoreの依存関係は以下の通りである.
build/core/Makefileにカットすると、システムイメージがINSTALLEDに依存していることがわかります.SYSTEMIMAGE、INSTALLED_SYSTEMIMAGEまたBUILTに頼ってSYSTEMIMAGE,BUILT_システメメメメジはシステムですimg
BUILTを見てみましょうSYSTEMIMAGEの依存関係:
BUILT_SYSTEMIMAGE依存のファイルが生成されると、makefileのbuild-systemimage-target関数が呼び出されます.次にbuild-systemimage-targetの関数のプロトタイプを見てみましょう.
複雑そうに見えますが、実はshell文ばかりで、よく見ると読めます.読めなくても大丈夫です.私たちはその中の肝心な文だけに関心を持っています./build/tools/releasetools/build_image.py、その後パラメータの山に従って、私たちはこれらのパラメータに関心を持つ必要はありません.理解すれば、ここでbuild_を呼び出しました.image.py build_を開くimage.py,main関数は以下のように複雑ではありません.ここでBuildImage()を呼び出します.
BuildImage()の表示を続行します.プロトタイプは次のとおりです.
この中にはたくさんのパラメータがありますが、実は非常に深い意味を持っています.私たちは学習段階で考慮する必要はありません.私たちが関連する問題に遭遇したとき、これらのパラメータと照らし合わせて、その機能と役割を理解する可能性があります.ここで重点的に見たのは、次のようなものです.
ここではmkuserimgを実行しましたmke2fs.shスクリプト、このスクリプトを見てみましょうパス:system/extras/ext 4_utils/mkuserimg_mke2fs.sh同様に、このファイルを開くとまたパラメータコマンドが山積みになっていることがわかり、見ても分からないが、私たちは依然としてその核心の部分に関心を持っているだけで、以下のように切り取っている.
ここでは,(1)mke 2 fsパッケージがsystemを生成することを2つ行った.img(2)e 2 fsdroidはsystemを作製した.map mke 2 fs対応ソースコード:external/e 2 fsprogs/misc/mke 2 fs.c e 2 fsdroid対応ソースコード:external/e 2 fsprogs/contrib/android/e 2 fsdroid.c
深く考える:実は、正常なandroidコンパイルではsystemは生成されません.map、最後のパラメータ$OUTPUT_のためFILEは空です.androidのデザインでsystem.mapは、OTAのtarget-filesファイルを作成する際に生成され、block差分を作成する際にsystemが使用する.map、1つのblock 1つのblockのdiffを求めます.OTAのtarget-filesを作成すると、systemが再パッケージされます.img、そのフロー:add_img_to_target_filesはbuild_を直接呼び出しましたimage.pyのCreateImage()関数は、通常のパッケージシステムと同じです.imgパラメータが少し違うので、ここでblock_を追加しましたList="system.map"パラメータなので、パッケージが終了するとsystemが生成する.map
Q & A: 1、system.imgはどのように作られていますか?答:mke 2 fsツールを用いて作成した2、system.mapは何に使いますか?先に持っていたシステムimg、やはり先に使ったシステムです.map? 答:system.mapはOTAのtarget-filesファイルを作成する際にsystemを再パッケージする.img後、system.imgが作ったシステムmapは、制作が悪い場合はsystemを使います.mapファイル
足りないところ、指摘を歓迎します!
.PHONY: droidcore
droidcore: files \
systemimage \
$(INSTALLED_BOOTIMAGE_TARGET) \
$(INSTALLED_RECOVERYIMAGE_TARGET) \
$(INSTALLED_VBMETAIMAGE_TARGET) \
$(INSTALLED_USERDATAIMAGE_TARGET) \
$(INSTALLED_CACHEIMAGE_TARGET) \
$(INSTALLED_BPTIMAGE_TARGET) \
$(INSTALLED_VENDORIMAGE_TARGET) \
$(INSTALLED_PRODUCTIMAGE_TARGET) \
$(INSTALLED_SYSTEMOTHERIMAGE_TARGET) \
$(INSTALLED_FILES_FILE) \
$(INSTALLED_FILES_FILE_VENDOR) \
$(INSTALLED_FILES_FILE_PRODUCT) \
$(INSTALLED_FILES_FILE_SYSTEMOTHER) \
soong_docs
build/core/Makefileにカットすると、システムイメージがINSTALLEDに依存していることがわかります.SYSTEMIMAGE、INSTALLED_SYSTEMIMAGEまたBUILTに頼ってSYSTEMIMAGE,BUILT_システメメメメジはシステムですimg
systemimage: $(INSTALLED_SYSTEMIMAGE)
$(INSTALLED_SYSTEMIMAGE): $(BUILT_SYSTEMIMAGE) $(RECOVERY_FROM_BOOT_PATCH)
BUILT_SYSTEMIMAGE := $(systemimage_intermediates)/system.img
BUILTを見てみましょうSYSTEMIMAGEの依存関係:
$(BUILT_SYSTEMIMAGE): $(FULL_SYSTEMIMAGE_DEPS) $(INSTALLED_FILES_FILE) $(BUILD_IMAGE_SRCS)
$(call build-systemimage-target,$@)
BUILT_SYSTEMIMAGE依存のファイルが生成されると、makefileのbuild-systemimage-target関数が呼び出されます.次にbuild-systemimage-targetの関数のプロトタイプを見てみましょう.
define build-systemimage-target
@echo "Target system fs image: $(1)"
$(call create-system-vendor-symlink)
@mkdir -p $(dir $(1)) $(systemimage_intermediates) && rm -rf $(systemimage_intermediates)/system_image_info.txt
$(call generate-userimage-prop-dictionary, $(systemimage_intermediates)/system_image_info.txt, \
skip_fsck=true)
$(hide) PATH=$(foreach p,$(INTERNAL_USERIMAGES_BINARY_PATHS),$(p):)$$PATH \
./build/tools/releasetools/build_image.py \
$(TARGET_OUT) $(systemimage_intermediates)/system_image_info.txt $(1) $(TARGET_OUT) \
|| ( echo "Out of space? the tree size of $(TARGET_OUT) is (MB): " 1>&2 ;\
du -sm $(TARGET_OUT) 1>&2;\
if [ "$(INTERNAL_USERIMAGES_EXT_VARIANT)" == "ext4" ]; then \
maxsize=$(BOARD_SYSTEMIMAGE_PARTITION_SIZE); \
if [ "$(BOARD_HAS_EXT4_RESERVED_BLOCKS)" == "true" ]; then \
maxsize=$$((maxsize - 4096 * 4096)); \
fi; \
echo "The max is $$(( maxsize / 1048576 )) MB." 1>&2 ;\
else \
echo "The max is $$(( $(BOARD_SYSTEMIMAGE_PARTITION_SIZE) / 1048576 )) MB." 1>&2 ;\
fi; \
mkdir -p $(DIST_DIR); cp $(INSTALLED_FILES_FILE) $(DIST_DIR)/installed-files-rescued.txt; \
exit 1 )
endef
複雑そうに見えますが、実はshell文ばかりで、よく見ると読めます.読めなくても大丈夫です.私たちはその中の肝心な文だけに関心を持っています./build/tools/releasetools/build_image.py、その後パラメータの山に従って、私たちはこれらのパラメータに関心を持つ必要はありません.理解すれば、ここでbuild_を呼び出しました.image.py build_を開くimage.py,main関数は以下のように複雑ではありません.ここでBuildImage()を呼び出します.
def main(argv):
if len(argv) != 4:
print __doc__
sys.exit(1)
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 dictionay 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 == "oem.img":
mount_point = "oem"
else:
print >> sys.stderr, "error: unknown image file name ", image_filename
exit(1)
image_properties = ImagePropFromGlobalDict(glob_dict, mount_point)
if not BuildImage(in_dir, image_properties, out_file, target_out):
print >> sys.stderr, "error: failed to build %s from %s" % (out_file,
in_dir)
exit(1)
BuildImage()の表示を続行します.プロトタイプは次のとおりです.
def BuildImage(in_dir, prop_dict, out_file, target_out=None):
"""Build an image to out_file from in_dir with property prop_dict.
Args:
in_dir: path of input directory.
prop_dict: property dictionary.
out_file: path of the output image file.
target_out: path of the product out directory to read device specific FS config files.
Returns:
True iff the image is built successfully.
"""
# system_root_image=true: build a system.img that combines the contents of
# /system and the ramdisk, and can be mounted at the root of the file system.
origin_in = in_dir
fs_config = prop_dict.get("fs_config")
base_fs_file = None
if (prop_dict.get("system_root_image") == "true"
and prop_dict["mount_point"] == "system"):
in_dir = tempfile.mkdtemp()
# Change the mount point to "/"
prop_dict["mount_point"] = "/"
if fs_config:
# We need to merge the fs_config files of system and ramdisk.
fd, merged_fs_config = tempfile.mkstemp(prefix="root_fs_config",
suffix=".txt")
os.close(fd)
with open(merged_fs_config, "w") as fw:
if "ramdisk_fs_config" in prop_dict:
with open(prop_dict["ramdisk_fs_config"]) as fr:
fw.writelines(fr.readlines())
with open(fs_config) as fr:
fw.writelines(fr.readlines())
fs_config = merged_fs_config
build_command = []
fs_type = prop_dict.get("fs_type", "")
run_fsck = False
fs_spans_partition = True
if fs_type.startswith("squash"):
fs_spans_partition = False
is_verity_partition = "verity_block_device" in prop_dict
verity_supported = prop_dict.get("verity") == "true"
verity_fec_supported = prop_dict.get("verity_fec") == "true"
# Adjust the partition size to make room for the hashes if this is to be
# verified.
if verity_supported and is_verity_partition:
partition_size = int(prop_dict.get("partition_size"))
(adjusted_size, verity_size) = AdjustPartitionSizeForVerity(partition_size,
verity_fec_supported)
if not adjusted_size:
return False
prop_dict["partition_size"] = str(adjusted_size)
prop_dict["original_partition_size"] = str(partition_size)
prop_dict["verity_size"] = str(verity_size)
# Adjust partition size for AVB hash footer or AVB hashtree footer.
avb_footer_type = ''
if prop_dict.get("avb_hash_enable") == "true":
avb_footer_type = 'hash'
elif prop_dict.get("avb_hashtree_enable") == "true":
avb_footer_type = 'hashtree'
if avb_footer_type:
avbtool = prop_dict["avb_avbtool"]
partition_size = prop_dict["partition_size"]
# avb_add_hash_footer_args or avb_add_hashtree_footer_args.
additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]
max_image_size = AVBCalcMaxImageSize(avbtool, avb_footer_type, partition_size,
additional_args)
if max_image_size == 0:
return False
prop_dict["partition_size"] = str(max_image_size)
prop_dict["original_partition_size"] = partition_size
if fs_type.startswith("ext"):
build_command = [prop_dict["ext_mkuserimg"]]
if "extfs_sparse_flag" in prop_dict:
build_command.append(prop_dict["extfs_sparse_flag"])
run_fsck = True
build_command.extend([in_dir, out_file, fs_type,
prop_dict["mount_point"]])
build_command.append(prop_dict["partition_size"])
if "journal_size" in prop_dict:
build_command.extend(["-j", prop_dict["journal_size"]])
if "timestamp" in prop_dict:
build_command.extend(["-T", str(prop_dict["timestamp"])])
if fs_config:
build_command.extend(["-C", fs_config])
if target_out:
build_command.extend(["-D", target_out])
if "block_list" in prop_dict:
build_command.extend(["-B", prop_dict["block_list"]])
if "base_fs_file" in prop_dict:
base_fs_file = ConvertBlockMapToBaseFs(prop_dict["base_fs_file"])
if base_fs_file is None:
return False
build_command.extend(["-d", base_fs_file])
build_command.extend(["-L", prop_dict["mount_point"]])
if "extfs_inode_count" in prop_dict:
build_command.extend(["-i", prop_dict["extfs_inode_count"]])
if "flash_erase_block_size" in prop_dict:
build_command.extend(["-e", prop_dict["flash_erase_block_size"]])
if "flash_logical_block_size" in prop_dict:
build_command.extend(["-o", prop_dict["flash_logical_block_size"]])
# Specify UUID and hash_seed if using mke2fs.
if prop_dict["ext_mkuserimg"] == "mkuserimg_mke2fs.sh":
if "uuid" in prop_dict:
build_command.extend(["-U", prop_dict["uuid"]])
if "hash_seed" in prop_dict:
build_command.extend(["-S", prop_dict["hash_seed"]])
if "selinux_fc" in prop_dict:
build_command.append(prop_dict["selinux_fc"])
elif fs_type.startswith("squash"):
build_command = ["mksquashfsimage.sh"]
build_command.extend([in_dir, out_file])
if "squashfs_sparse_flag" in prop_dict:
build_command.extend([prop_dict["squashfs_sparse_flag"]])
build_command.extend(["-m", prop_dict["mount_point"]])
if target_out:
build_command.extend(["-d", target_out])
if fs_config:
build_command.extend(["-C", fs_config])
if "selinux_fc" in prop_dict:
build_command.extend(["-c", prop_dict["selinux_fc"]])
if "block_list" in prop_dict:
build_command.extend(["-B", prop_dict["block_list"]])
if "squashfs_compressor" in prop_dict:
build_command.extend(["-z", prop_dict["squashfs_compressor"]])
if "squashfs_compressor_opt" in prop_dict:
build_command.extend(["-zo", prop_dict["squashfs_compressor_opt"]])
if "squashfs_block_size" in prop_dict:
build_command.extend(["-b", prop_dict["squashfs_block_size"]])
if "squashfs_disable_4k_align" in prop_dict and prop_dict.get("squashfs_disable_4k_align") == "true":
build_command.extend(["-a"])
elif fs_type.startswith("f2fs"):
build_command = ["mkf2fsuserimg.sh"]
build_command.extend([out_file, prop_dict["partition_size"]])
else:
print("Error: unknown filesystem type '%s'" % (fs_type))
return False
if in_dir != origin_in:
# Construct a staging directory of the root file system.
ramdisk_dir = prop_dict.get("ramdisk_dir")
if ramdisk_dir:
shutil.rmtree(in_dir)
shutil.copytree(ramdisk_dir, in_dir, symlinks=True)
staging_system = os.path.join(in_dir, "system")
shutil.rmtree(staging_system, ignore_errors=True)
shutil.copytree(origin_in, staging_system, symlinks=True)
has_reserved_blocks = prop_dict.get("has_ext4_reserved_blocks") == "true"
ext4fs_output = None
try:
if fs_type.startswith("ext4"):
(ext4fs_output, exit_code) = RunCommand(build_command)
else:
(_, exit_code) = RunCommand(build_command)
finally:
if in_dir != origin_in:
# Clean up temporary directories and files.
shutil.rmtree(in_dir, ignore_errors=True)
if fs_config:
os.remove(fs_config)
if base_fs_file is not None:
os.remove(base_fs_file)
if exit_code != 0:
return False
# Bug: 21522719, 22023465
# There are some reserved blocks on ext4 FS (lesser of 4096 blocks and 2%).
# We need to deduct those blocks from the available space, since they are
# not writable even with root privilege. It only affects devices using
# file-based OTA and a kernel version of 3.10 or greater (currently just
# sprout).
# Separately, check if there's enough headroom space available. This is useful for
# devices with low disk space that have system image variation between builds.
if (has_reserved_blocks or "partition_headroom" in prop_dict) and fs_type.startswith("ext4"):
assert ext4fs_output is not None
ext4fs_stats = re.compile(
r'Created filesystem with .* (?P[0-9]+)/'
r'(?P[0-9]+) blocks')
m = ext4fs_stats.match(ext4fs_output.strip().split('
')[-1])
used_blocks = int(m.groupdict().get('used_blocks'))
total_blocks = int(m.groupdict().get('total_blocks'))
reserved_blocks = 0
headroom_blocks = 0
adjusted_blocks = total_blocks
if has_reserved_blocks:
reserved_blocks = min(4096, int(total_blocks * 0.02))
adjusted_blocks -= reserved_blocks
if "partition_headroom" in prop_dict:
headroom_blocks = int(prop_dict.get('partition_headroom')) / BLOCK_SIZE
adjusted_blocks -= headroom_blocks
if used_blocks > adjusted_blocks:
mount_point = prop_dict.get("mount_point")
print("Error: Not enough room on %s (total: %d blocks, used: %d blocks, "
"reserved: %d blocks, headroom: %d blocks, available: %d blocks)" % (
mount_point, total_blocks, used_blocks, reserved_blocks,
headroom_blocks, adjusted_blocks))
return False
if not fs_spans_partition:
mount_point = prop_dict.get("mount_point")
partition_size = int(prop_dict.get("partition_size"))
image_size = GetSimgSize(out_file)
if image_size > partition_size:
print("Error: %s image size of %d is larger than partition size of "
"%d" % (mount_point, image_size, partition_size))
return False
if verity_supported and is_verity_partition:
ZeroPadSimg(out_file, partition_size - image_size)
# create the verified image if this is to be verified
if verity_supported and is_verity_partition:
if not MakeVerityEnabledImage(out_file, verity_fec_supported, prop_dict):
return False
# Add AVB HASH or HASHTREE footer (metadata).
if avb_footer_type:
avbtool = prop_dict["avb_avbtool"]
original_partition_size = prop_dict["original_partition_size"]
partition_name = prop_dict["partition_name"]
# key_path and algorithm are only available when chain partition is used.
key_path = prop_dict.get("avb_key_path")
algorithm = prop_dict.get("avb_algorithm")
salt = prop_dict.get("avb_salt")
# avb_add_hash_footer_args or avb_add_hashtree_footer_args
additional_args = prop_dict["avb_add_" + avb_footer_type + "_footer_args"]
if not AVBAddFooter(out_file, avbtool, avb_footer_type, original_partition_size,
partition_name, key_path, algorithm, salt, additional_args):
return False
if run_fsck and prop_dict.get("skip_fsck") != "true":
success, unsparse_image = UnsparseImage(out_file, replace=False)
if not success:
return False
# Run e2fsck on the inflated image file
e2fsck_command = ["e2fsck", "-f", "-n", unsparse_image]
(_, exit_code) = RunCommand(e2fsck_command)
os.remove(unsparse_image)
return exit_code == 0
この中にはたくさんのパラメータがありますが、実は非常に深い意味を持っています.私たちは学習段階で考慮する必要はありません.私たちが関連する問題に遭遇したとき、これらのパラメータと照らし合わせて、その機能と役割を理解する可能性があります.ここで重点的に見たのは、次のようなものです.
if prop_dict["ext_mkuserimg"] == "mkuserimg_mke2fs.sh":
if "uuid" in prop_dict:
build_command.extend(["-U", prop_dict["uuid"]])
if "hash_seed" in prop_dict:
build_command.extend(["-S", prop_dict["hash_seed"]])
ここではmkuserimgを実行しましたmke2fs.shスクリプト、このスクリプトを見てみましょうパス:system/extras/ext 4_utils/mkuserimg_mke2fs.sh同様に、このファイルを開くとまたパラメータコマンドが山積みになっていることがわかり、見ても分からないが、私たちは依然としてその核心の部分に関心を持っているだけで、以下のように切り取っている.
MAKE_EXT4FS_CMD="mke2fs $MKE2FS_OPTS -t $EXT_VARIANT -b $BLOCKSIZE $OUTPUT_FILE $SIZE"
echo $MAKE_EXT4FS_ENV $MAKE_EXT4FS_CMD
env $MAKE_EXT4FS_ENV $MAKE_EXT4FS_CMD
if [ $? -ne 0 ]; then
exit 4
fi
if [[ $E2FSPROGS_FAKE_TIME ]]; then
E2FSDROID_ENV="E2FSPROGS_FAKE_TIME=$E2FSPROGS_FAKE_TIME"
fi
E2FSDROID_CMD="e2fsdroid $E2FSDROID_OPTS -f $SRC_DIR -a $MOUNT_POINT $OUTPUT_FILE"
echo $E2FSDROID_ENV $E2FSDROID_CMD
env $E2FSDROID_ENV $E2FSDROID_CMD
if [ $? -ne 0 ]; then
rm -f $OUTPUT_FILE
exit 4
fi
ここでは,(1)mke 2 fsパッケージがsystemを生成することを2つ行った.img(2)e 2 fsdroidはsystemを作製した.map mke 2 fs対応ソースコード:external/e 2 fsprogs/misc/mke 2 fs.c e 2 fsdroid対応ソースコード:external/e 2 fsprogs/contrib/android/e 2 fsdroid.c
深く考える:実は、正常なandroidコンパイルではsystemは生成されません.map、最後のパラメータ$OUTPUT_のためFILEは空です.androidのデザインでsystem.mapは、OTAのtarget-filesファイルを作成する際に生成され、block差分を作成する際にsystemが使用する.map、1つのblock 1つのblockのdiffを求めます.OTAのtarget-filesを作成すると、systemが再パッケージされます.img、そのフロー:add_img_to_target_filesはbuild_を直接呼び出しましたimage.pyのCreateImage()関数は、通常のパッケージシステムと同じです.imgパラメータが少し違うので、ここでblock_を追加しましたList="system.map"パラメータなので、パッケージが終了するとsystemが生成する.map
Q & A: 1、system.imgはどのように作られていますか?答:mke 2 fsツールを用いて作成した2、system.mapは何に使いますか?先に持っていたシステムimg、やはり先に使ったシステムです.map? 答:system.mapはOTAのtarget-filesファイルを作成する際にsystemを再パッケージする.img後、system.imgが作ったシステムmapは、制作が悪い場合はsystemを使います.mapファイル
足りないところ、指摘を歓迎します!