日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

System.img是如何打包的

發布時間:2025/3/21 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 System.img是如何打包的 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

★★★ 友情鏈接 : 個人博客導讀首頁—點擊此處 ★★★

當敲擊make命令時,會找到第一個目標droid(在build/core/main.mk中),droid依賴droid_targets,droid_targets依賴droidcore和dist_files,droidcore的依賴關系如下:

.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中,我們看到systemimage又依賴INSTALLED_SYSTEMIMAGE,而INSTALLED_SYSTEMIMAGE又依賴BUILT_SYSTEMIMAGE,BUILT_SYSTEMIMAGE其實就是system.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_dictelse: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_filenameexit(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_dirfs_config = prop_dict.get("fs_config")base_fs_file = Noneif (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_configbuild_command = []fs_type = prop_dict.get("fs_type", "")run_fsck = Falsefs_spans_partition = Trueif fs_type.startswith("squash"):fs_spans_partition = Falseis_verity_partition = "verity_block_device" in prop_dictverity_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 Falseprop_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 Falseprop_dict["partition_size"] = str(max_image_size)prop_dict["original_partition_size"] = partition_sizeif 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 = Truebuild_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 Falsebuild_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 Falseif 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 = Nonetry: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 Noneext4fs_stats = re.compile(r'Created filesystem with .* (?P<used_blocks>[0-9]+)/'r'(?P<total_blocks>[0-9]+) blocks')m = ext4fs_stats.match(ext4fs_output.strip().split('\n')[-1])used_blocks = int(m.groupdict().get('used_blocks'))total_blocks = int(m.groupdict().get('total_blocks'))reserved_blocks = 0headroom_blocks = 0adjusted_blocks = total_blocksif has_reserved_blocks:reserved_blocks = min(4096, int(total_blocks * 0.02))adjusted_blocks -= reserved_blocksif "partition_headroom" in prop_dict:headroom_blocks = int(prop_dict.get('partition_headroom')) / BLOCK_SIZEadjusted_blocks -= headroom_blocksif 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 Falseif 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 Falseif verity_supported and is_verity_partition:ZeroPadSimg(out_file, partition_size - image_size)# create the verified image if this is to be verifiedif 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_argsadditional_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 Falseif 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 filee2fsck_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/ext4_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 ]; thenexit 4 fiif [[ $E2FSPROGS_FAKE_TIME ]]; thenE2FSDROID_ENV="E2FSPROGS_FAKE_TIME=$E2FSPROGS_FAKE_TIME" fiE2FSDROID_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 ]; thenrm -f $OUTPUT_FILEexit 4 fi

這里做了兩件事:
(1)mke2fs打包生成了system.img
(2)e2fsdroid制作了system.map
mke2fs對應的源碼:external/e2fsprogs/misc/mke2fs.c
e2fsdroid對應的源碼 : external/e2fsprogs/contrib/android/e2fsdroid.c

深思:
其實呢,在正常的android編譯,并不會生成system.map,因為最后一個參數$OUTPUT_FILE為空. 在android的設計中system.map是在制作OTA的target-files文件時生成的,然后在制作block差分別時候,會用到system.map,一個block一個block的去求diff。
在制作OTA的target-files時,會重新打包system.img,其流程:
add_img_to_target_files直接調用了build_image.py中的CreateImage()函數,與正常的打包system.img參數稍微不同,這里增加了一個block_list="system.map"參數,所以其打包結束后,生成了system.map

Q & A:
1、system.img是怎樣制作的?
答:使用mke2fs工具制作的
2、system.map是做什么用的?先有的system.img,還是先用的system.map?
答:system.map是制作OTA的target-files文件時,重新打包system.img后,根據system.img做出的system.map,制作差分別時候,會用到system.map文件

不足之處,歡迎指正!

總結

以上是生活随笔為你收集整理的System.img是如何打包的的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 美女毛片| 99国内精品| 成年人的天堂 | 国产一级片子 | 国产极品福利 | 性饥渴的农村熟妇 | 色www.| 亚洲乱色熟女一区二区三区 | 优优色综合| 日韩欧美啪啪 | 中文在线免费 | 亚洲制服av | a级黄毛片 | 污污网站在线免费观看 | 少妇人妻互换不带套 | 九色丨蝌蚪丨成人 | 国外成人免费视频 | 欧美色久 | 爱插美女网| 日本中文有码 | 澳门黄色 | 青青草在线免费观看 | 又黄又免费的网站 | 亚洲精品网站在线 | 少妇荡乳情欲办公室456视频 | 亚州色图欧美色图| 女生被男生c | 欧美成人免费播放 | a级片一区二区 | 亚洲精品久久久久久久蜜桃 | 一级黄色片在线播放 | 日美av| 三级视频网站在线观看 | 天天干天天爱天天操 | 欧美日日操 | 草草影院国产第一页 | 欧美在线视频免费观看 | 欧美成人精品一区二区男人看 | 精品国模一区二区三区欧美 | 成人福利视频 | 99视频在线观看视频 | 一区二区在线免费视频 | 黄色网页免费看 | 2024国产精品视频 | 男生和女生靠逼视频 | 免费在线 | 中文字幕高清在线免费播放 | 亚洲色婷婷一区二区三区 | 91亚洲精品在线 | 97caocao| 日韩欧美一区视频 | 国产一区二区久久久 | 日本成人在线免费观看 | 精品一区二区免费 | 三级黄色图片 | 99热影院| 成年人免费观看视频网站 | 欧美日韩黄色 | 色婷婷久久综合中文久久蜜桃av | 午夜伊人网 | 丁香花高清视频完整电影 | 美女在线免费视频 | 亚洲第一视频网站 | 精品久久福利 | 粉嫩av一区二区三区四区五区 | 潘金莲一级淫片aaaaaa播放 | 成人福利在线播放 | 久久精品免费观看 | 国产三级理论片 | 催眠调教艳妇成肉便小说 | 狂野欧美性猛交xxxx777 | 欧美极品第一页 | 日韩中文字幕在线看 | 91欧美在线视频 | aa视频在线 | 福利视频大全 | 欧美日本高清 | 手机在线播放av | 每日更新在线观看av | 黄色日皮视频 | 女性裸体不遮胸图片 | 日本在线观看一区二区 | 国产一区二区片 | 欧美精品99久久 | 黄色精品网站 | 国产自产一区二区 | 久久性网 | 高清视频一区 | 免费在线播放毛片 | h片在线观看视频 | 亚洲免费视频播放 | 欧美性视频播放 | 天天干天天操天天 | 国产精品国产精品 | 综合色在线观看 | 欧美伦理在线观看 | 潘金莲一级淫片aaaaa武则天 | 国产黄色片在线播放 | 欧美三级又粗又硬 |