zoukankan      html  css  js  c++  java
  • 优化嵌入式Linux的启动时间之文件系统

    导读:嵌入式Linux在应用中往往希望系统能在尽量短的时间内启动,以提高用户体验。而且在有的应用场合,对启动时间具有严格的时间要求,尤其在工业或者医疗器械应用领域。此时如何加快Linux的启动,将成为一个挑战,对于大多数应用开发人员而言,由于Linux系统的复杂性,对于如何提高启动速度,往往无从下手。那么读完优化嵌入式Linux的启动时间系列文章,将获得清晰完整的解决思路。本文将从优化文件系统的角度探讨如何缩短启动时间。

    1.文件系统
    不同的存储介质会采用不同的文件系统:
    在这里插入图片描述1)块存储介质 (包括存储卡, eMMC):
    - ext2, ext3,ext4
    - xfs, jfs,reiserfs
    - btrfs
    - f2fs
    - SquashFS
    2)Raw 闪存:
    - JFFS2
    - YAFFS2
    - UBIFS
    - ubiblock +SquashFS

    对于块文件系统,特性各异:

    • ext4:最适合较大的分区,良好的读写性能。
    • xfs,jfs,reiserfs:在某些读或写场景中也可能很好。
    • btrfs,f2fs:利用闪存块设备的特性,可以实现最佳的读写性能。
    • SquashFS:对于只读分区,最佳挂载时间和读取性能。非常适合需要只读的根文件系统。
      下面分别介绍各文件系统的详细特性。

    1.1. JFFS2
    用于RAW Flash:

    • 挂载时间取决于文件系统的大小:内核必须在挂载时扫描整个文件系统,以读取属于每个文件的块。
    • 需要使用CONFIG_JFFS2_SUMMARY内核选项将此类信息存储在Flash中。这大大减少了安装时间。
    • ARM基准:对于128 MB分区,从16 s到0.8 s。
    • 与YAFFS2和UBIFS相比,读写性能相当差。

    1.3 YAFFS2
    用于RAW Flash:

    • 良好的安装时间
    • 良好的读写性能
    • 缺点:不压缩,不在主线Linux内核中

    1.4. UBIFS
    用于RAW Flash:

    • 优势:
      良好的读写性能(类似于YAFFS2)
      其他优点:更好的磨损均衡(不仅可以在单个分区内,而且可以在整个UBI空间中使用)。
    • 缺点:
      不适用于小型分区(元数据开销过多)。请改用JFFS2或JAFFS2。
      挂载时间不是很好,因为初始化UBI需要时间(UBI Attach:在引导时或在用户空间中运行ubi_attach)。
      由Linux 3.7中引入的UBI Fastmap解决。

    1.5. UBI Fastmap如何工作

    • UBI 加载:需要通过扫描所有擦除块来读取UBI元数据。时间与存储空间成正比。
    • UBI Fastmap将此类信息存储在几个闪存块中(通常在系统关闭期间在UBI分离时),并在引导时找到该信息。
    • 这样可使UBI附加时间恒定。
    • 如果Fastmap信息无效(例如,不正常的系统关闭),它将退回到扫描状态(速度较慢,但能保证正确,Fastmap在下次启动时将恢复)。
    • 详细信息:Thomas Gleixner的ELCE 2012演讲:
      http://elinux.org/images/a/ab/UBI_Fastmap.pdf

    使用步骤:

    • 使用CONFIG_UBI_FASTMAP配置编译内核
    • 使用ubi.fm_autoconvert = 1内核参数至少引导一次系统。
    • 以干净的方式重启系统
    • 保证如上启动一次后可以删除ubi.fm_autoconvert = 1

    UBI Fastmap性能测试举例:

    • 在Linux 3.10的Microchip SAMA5D3 Xplained板(ARM)上测得
      1.UBI空间:216 MB
      2.根文件系统:已使用80 MB(Yocto)
      3.平均加载时间:
      a.无UBI Fastmap,加载时间:968ms
      b.有UBI Fastmap,加载时间:238 ms
      可见UBI Fastmap 改善非常显著!

    1.6. ubiblock + SquashFS
    对RAW Flash :

    • ubiblock:位于UBI顶部的只读块设备
      利用CONFIG_MTD_UBI_BLOCK配置编译。

    • 允许将SquashFS放在UBI卷上。

    • 引导时间和读取性能不错。非常适合于只读根文件系统。

    2. 选取合适的文件系统

    • RAW Flash :带有CONFIG_UBI_FASTMAP的UBIFS可能是最佳解决方案。

    • 块存储:SquashFS是根文件系统的最佳解决方案,它可以是只读的。Btrfs和f2fs可能是读/写文件系统的最佳解决方案。

    • 更改文件系统类型非常容易,并且对应用程序完全透明。只需尝试几个文件系统选项,看看哪个最适合!
      不要只关注启动时间。
      对于读写性能至关重要的系统,我们建议使用单独的根文件系统(以加快启动时间)和数据分区(以实现良好的运行时性能)。

    2.1 Initramfs
    一个很好的方案是使用非常小的initramfs,以启动关键应用程序,然后切换到最终的根文件系统。在这里插入图片描述
    initramfs机制:将根文件系统集成到内核映像中,因此它与内核一起被加载到内存中:

    • 它将文件系统的压缩存档集成到内核映像中
    • 变种:压缩的initramfs固件也可以由bootloader单独加载。

    initramfs在下面两种情况下非常有用:

    • 快速启动且非常小的根文件系统。由于文件系统在启动时已完全加载,因此应用程序启动也非常快。
    • 作为切换到实际根文件系统之前的中间步骤,该文件位于需要其驱动程序不属于内核映像的设备(存储驱动程序,文件系统驱动程序,网络驱动程序)上。始终在桌面/服务器发行版的内核上使用此选项,以保持内核映像大小合理。

    2.2 内存中的initramfs
    在这里插入图片描述

    • 使用CONFIG_INITRAMFS_SOURCE选项在内核配置级别定义initramfs的内容
      1.可以是包含根文件系统内容的目录的路径
      2.可以是cpio归档文件的路径
      3.可以是描述initramfs内容的文本文件

    • 内核构建过程将自动获取CONFIG_INITRAMFS_SOURCE选项配置的内容,并将根文件系统集成到内核映像中

    • 详细信息(在内核源文件中):
      Documentation/filesystems/ramfs-rootfs-initramfs.txt
      Documentation/early-userspace/README

    2.3 用initramfs启动过程
    在这里插入图片描述
    2.4 initramfs 降低启动时间
    创建尽可能小的最小初始化文件,足以启动关键应用程序,然后使用switch_root切换到最终根文件系统:

    • 使用轻量级的C库以减小固件大小,建议使用uClibc。
    • 将BusyBox裁剪到最小。甚至可以不用BusyBox直接在C中实现/init。
    • 使用静态链接的应用程序(较少的CPU开销,较少的库加载,较小的initramfs(如果根本没有库))。Buildroot中用BR2_STATIC_LIBS配置。

    2.5 静态链接可执行文件

    • 静态链接的可执行文件对于减小大小(特别是在小型initramfs中)非常有用,并且启动工作量较少。
    • 如果您将initramfs放在压缩的内核映像中,请不要对其进行压缩(启用CONFIG_INITRAMFS_COMPRESSION_NONE)。
    • 否则默认情况下,您的initramfs数据将被压缩两次,内核将更大,并且将花费更多的时间来加载和解压缩。
    • 在Linux 5.1上的示例在Beagle Bone Black上具有1.60 MB的initramfs(tar存档大小):这可以将内核大小从4.94 MB减少到4.74 MB(-200 KB),并节省大约170毫秒的启动时间。

    后续会发布:

    • 优化嵌入式Linux的启动时间之内核
    • 优化嵌入式Linux的启动时间之bootloader
      敬请关注!

    码字不易若您觉得文章不错,不妨转发分享,点点在看,亦或者小小打赏,都将激励我们持续更新。
    关注公众号扫左下二维码,关注公众号内容更丰富
    回复“领取资源”可领取liunx、安卓视频教程、人工智能视频等学习资料。

    ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200303220245653.png?在这里插入图片描述
    在这里插入图片描述

    为节约时间,文章同步自公众号(首发) 如需学习资料,请用微信关注文中公众号二维码,后台发送"领取",可免费获取海量学习资料,涵盖单片机技术,信号处理,人工智能,嵌入式linux,C/C++编程,数据结构与算法
  • 相关阅读:
    @RequestParam注解使用:Name for argument type [java.lang.String] not available, and parameter name information not found in class file either.
    cglib动态代理导致注解丢失问题及如何修改注解允许被继承
    springboot Autowired BeanNotOfRequiredTypeException
    git根据用户过滤提交记录
    不同包下,相同数据结构的两个类进行转换
    How to use Jackson to deserialise an array of objects
    jooq实践
    java如何寻找main函数对应的类
    Python--matplotlib
    Python 和 Scikit-Learn
  • 原文地址:https://www.cnblogs.com/embInn/p/14038156.html
Copyright © 2011-2022 走看看