2天时间,聊今年最热的 Agent、上下文工程、AI 产品创新等话题。2025 年最后一场~ 了解详情
写点什么

怎样在 1 秒内启动 Linux

  • 2015-12-02
  • 本文字数:1925 字

    阅读完需:约 6 分钟

尽可能快的启动系统,对于自动化设备是非常重要的。系统能够在用户无法感知的时间内启动,也就意味着在不需要工作时,可以完全切断电源,而不是挂起进入休眠状态。本文基于 Atmel AT91 系列片上系统和 NAND 闪存,经过一系列的优化,将 Linux 系统启动时间,从最初的 11 秒,降低到最终的 656 毫秒。

背景知识

系统从上电到完全启动,需要经过许多过程。一个简化的启动流程大概包含:

  1. 硬件重置
  2. 启动引导程序(bootloader)
  3. 操作系统初始化
  4. 应用程序执行

其中硬件非常关键,但是硬件一般难以更改。后续的优化,主要针对引导程序、Linux 内核和应用程序展开。

引导程序优化

引导程序主要完成对 CPU 的基础设置,处理 ARM 标记(ATAGS,ARM TAGS)或设备树(device trees),切换存储管理单元(MMU,Memory Management Unit)等工作。

重要通知:接下来 InfoQ 将会选择性地将部分优秀内容首发在微信公众号中,欢迎关注 InfoQ 微信公众号第一时间阅读精品内容。

对于 U-Boot,常用的优化方式有:

  • 删除不不要的功能:如网络加载等,如果不需要,那么直接移除这些代码吧;
  • 关闭不需要的功能
    • 关闭内核镜像验证
    • 关闭引导程序输出
    • 关闭启动延迟
  • 将通用功能的引导程序修改成一个优化后的初始程序加载器(Initial Program Loader,IPL),对于 U-Boot,可以通过 SPL(Second Program Loader,第二阶段程序加载器)来实现。

内核优化

Linux 内核被设计的非常灵活,可以针对需要的功能做各种配置优化。因此,优化内核对于系统启动速度是至关重要的。

首先,移除一切不要的驱动,尽可能的减少内核加载的内容,能够大大缩短系统启动时间。其次,还有很多内核选择可能需要进一步尝试,比如内核压缩方式,对于嵌入式系统来说,LZO 压缩方式,通常会是一个不错的选择。最后,还可以通过定制一些启动参数,达到加快启动的目的。例如可以通过“lpj=”参数,预设每个循环需要的节拍数(loops per jiffy,lpj)的值,避免系统在启动时自动推算。这样在基于 ARMv5 的系统中,可以节省 100ms 以上的时间。

对于内核启动的优化,可以通过 bootgraph.pl 脚本(位于内核源码的 script/bootgraph.pl )来绘制内核启动耗时图表,用以分析启动最耗时的地方。这个脚本使用非常简单,直接将 dmesg 的输出作为其输入,即可生成 svg 图表:

dmesg | perl scripts/bootgraph.pl > output.svg生成的图表如下图,

图中每一个色段表示一个功能的初始化耗时。可以简单的关闭不需要的功能,或者针对功能进行特定的优化。

除了内核本身之外,内核所在的文件系统也对系统启动有着非常大的影响。对于使用闪存芯片作为存储的系统来说, UbiFS 是一个很好的选择。它能够容忍意外断电,有着出色的挂载速度,以确保系统快速启动。

应用程序优化

内核完成系统启动之后,接来下就是执行应用程序。对于应用程序的优化,主要有两部分,一部分是由应用程序来接管启动的 INIT 进程,另一部分是优化应用程序的链接方式。

标准的 SystemV INIT 程序,需要执行一堆启动脚本。对于嵌入式系统来说,大部分是没有意义的。另一部分(比如挂载文件系统),可以由应用程序自己来实现。然后,可以在内核启动参数中通过“init=”参数,将 INIT 进程直接指定为应用程序。

应用依赖的动态链接库,会按照以下顺序查找:

  1. LD_PRELOAD 环境变量指定的路径(一般对应文件 /etc/ld.so.preload);
  2. ELF .dynamic 节中 DT_RPATH 入口指定的路径,若 DT_RUNPATH 入口不存在的话;
  3. 环境变量 LD_LIBRARY_PATH 指定的路径,但如果可执行文件有 setuid/setgid 权限,则忽略这个路径;编译时指定–library-path 会覆盖这个路径;
  4. ELF .dynamic 节中 DT_RUNPATH 入口指定的路径;
  5. ldconfig 缓存中的路径(一般对应 /etc/ld.so.cache 文件),若编译时使用了 -z nodeflib 的链接选项,则此步跳过;
  6. /lib,然后 /usr/lib 路径 ,若使用了 -z nodeflib 链接选项,则此步亦跳过;

因此,尽可能的将应用程序依赖的动态链接库放到优先查找的路径,可以加快链接速度。对于交叉编译环境特别需要注意,主机上的动态链接库位置和目标系统上的位置可能不一致,这会增加应用程序执行时动态链接库的加载时间。

总结

基于上面提到的三个优化点,可以将系统的启动时间,从最初的 11s 降低到 656ms(数据参考 Jan Altenberg 在都柏林举行的嵌入式 Linux 会议上的演讲稿)。从硬件到引导程序再到内核最后到应用程序,每个启动步骤都有自己可优化的地方,经过一些简单的优化,就可以减少系统的启动时间。


感谢魏星对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入 InfoQ 读者交流群(已满),InfoQ 读者交流群(#2))。

2015-12-02 18:005112

评论

发布
暂无评论
发现更多内容

干货分享!用心满满:面试前必知必会的二分查找及其变种

比伯

Java 编程 架构 面试 计算机

研发管理:敏捷研发下周报的价值

云原生实验室

云原生 敏捷 研发管理 周报

5G多输入多输出技术,到底是个啥东东?

华为云开发者联盟

5G 输入 输出

架构师训练营第 1 期 第 11 周作业

李循律

极客大学架构师训练营

深度学习在物理层信号处理中的应用研究

华为云开发者联盟

学习 模型 物理层

架构探索:事务处理一

Dark

基于RTMP数据传输协议的实时流媒体技术研究(论文全文)

程序员小灰

音视频 ffmpeg 流媒体 RTMP webrtc、

mongodb 源码实现系列 - command 命令处理模块源码实现二

杨亚洲腾讯科技

MySQL mongodb 分布式数据库 源码刨析 分布式数据库mongodb

云原生架构:容器资源限制及资源可见性

云原生实验室

云原生

为什么阿里人能够快速成长?看完他们Java架构进化笔记,我秒懂!

Java架构追梦

Java 学习 架构 面试 成长笔记

拆解增长黑客之实战(一):获客与激活

懒杨杨

增长 产品运营

流动性挖矿系统APP开发|流动性挖矿软件开发

系统开发

CloudIDE插件开发实战:教你如何调试代码

华为云开发者联盟

ide 开发 Cloud

前端开发还可以这么玩?元数据实践分享

华为云开发者联盟

大前端 元数据 组件 ROMA 业务流

深入灵魂的考验,每行注释都是灵魂的单例模式,源码+实例降临

小Q

Java 学习 架构 面试 设计模式

全球熵ETV系统APP开发|全球熵ETV软件开发

系统开发

三分钟看懂快速开发,常用软件快速开发平台速览

Marilyn

敏捷开发 快速开发 企业开发 企业应用

揭秘 VMAF 视频质量评测标准

阿里云CloudImagine

视频 图像处理

《Web自动化》基础知识脑图

清菡软件测试

Web

anyRTC 联合 vInClass 打造在线教育上课模式

anyRTC开发者

音视频 WebRTC 在线教育 RTC

理解Python协程的本质

Justfly

Python 协程 异步 Async 异步编程

多活/多机房的几种实现方式与重点

Justfly

高可用 跨机房 数据同步 异地多活容灾

Linux角度仰视Goroutine的GMP

ninetyhe

Java Linux 多线程与高并发 Go 语言

工商银行基于 Dubbo 构建金融微服务架构的实践-服务发现篇

阿里巴巴云原生

云原生 dubbo 中间件 案例分享 CloudNative

构师训练营 - 第七周课后练习

joshuamai

王者级别的Java多线程技术笔记,我愿奉你为地表最强!

Java架构师迁哥

构师训练营 - 第七周学习总结

joshuamai

告别“效率内卷化”,华为用一年时间让职场人支棱起来

脑极体

鹅厂大佬亲身经历证明,一周上线百万级并发系统

Java架构师迁哥

InfoQ 内容推荐位资源限时开放

乐白

InfoQ 资源

WebRTC SDP 详解和剖析

阿里云CloudImagine

阿里云 音视频 WebRTC 视频云 流媒体传输

怎样在1秒内启动Linux_Linux_金灵杰_InfoQ精选文章