Linux系统管理 启动时间的极限优化方案

本文详细介绍了通过跟踪内核启动过程、分析时间报告、优化关键环节来减少Linux启动时间的方法,最终将启动时间从7秒优化至2秒以内,显著提升了设备的可靠性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在上次完成嵌入式应用的Linux裁减后,Linux的启动时间仍需要 7s 左右,虽然勉强可以接受,但仍然没有达到我个人所追求的目标——2s 以内。况且,在实际的商用环境中,设备可靠性的要求可是“5个9”(99.999%,即OOS时间低于5分钟/年),这就意味着每减少一秒钟Linux启动(设备复位)时间,对可靠性都是一个明显的提升。

  言归正传,如何着手对Linux的启动时间进行优化呢?

  CELF(The Consumer Electronics Linux Forum)论坛为我们指引了一个方向。

  (1)首先是对Linux启动过程的跟踪和分析,生成详细的启动时间报告。

  较为简单可行的方式是通过PrintkTime功能为启动过程的所有内核信息增加时间戳,便于汇总分析。PrintkTime最早为CELF所提供的一个内核补丁,在后来的Kernel 2.6.11版本中正式纳入标准内核。所以大家可能在新版本的内核中直接启用该功能。如果你的Linux内核因为某些原因不能更新为2.6.11之后的版本,那么可以参考CELF提供的方法修改或直接下载它们提供的补丁:http://tree.celinuxforum.org/CelfPubWiki/PrintkTimes

  开启PrintkTime功能的方法很简单,只需在内核启动参数中增加“time”即可。当然,你也可以选择在编译内核时直接指定“Kernel hacking”中的“Show timing information on printks”来强制每次启动均为内核信息增加时间戳。这一种方式还有另一个好处:你可以得到内核在解析启动参数前所有信息的时间。因此,我选择后一种方式。

  当完成上述配置后,重新启动Linux,然后通过以下命令将内核启动信息输出到文件:

dmesg -s 131072 > ktime

  然后利用一个脚本“show_delta”(位于Linux源码的scripts文件夹下)将上述输出的文件转换为时间增量显示格式:

  /usr/src/linux-x.xx.xx/scripts/show_delta ktime > dtime

  这样,你就得到了一份关于Linux启动时间消耗的详细报告。

  (2)然后,我们就来通过这份报告,找出启动中相对耗时的过程。

  必须明确一点:报告中的时间增量和内核信息之间没有必然的对应关系,真正的时间消耗必须从内核源码入手分析。

  这一点对于稍微熟悉编程的朋友来说都不难理解,因为时间增量只是两次调用printk之间的时间差值。通常来说,内核启动过程中在完成一些耗时的任务,如创建hash索引、probe硬件设备等操作后会通过printk将结果打印出来,这种情况下,时间增量往往反映的是信息对应过程的耗时;但有些时候,内核是在调用printk输出信息后才开始相应的过程,那么报告中内核信息相应过程的时间消耗对应的是其下一行的时间增量;还有一些时候,时间消耗在了两次内核信息输出之间的某个不确定的时段,这样时间增量可能就完全无法通过内核信息反应出来了。

  所以,为了准确判断真正的时间消耗,我们需要结合内核源码进行分析。必要的时候,例如上述第三种情形下,还得自己在源码中插入printk打印,以进一步确定实际的时间消耗过程。

  以下是我上次裁减后Linux内核的启动分析:

  内核启动总时间: 6.188s

  关键的耗时部分:
  1) 0.652s - Timer,IRQ,Cache,Mem Pages等核心部分的初始化
  2) 0.611s - 内核与RTC时钟同步
  3) 0.328s - 计算Calibrating Delay(4个CPU核心的总消耗)
  4) 0.144s - 校准APIC时钟
  5) 0.312s - 校准Migration Cost
  6) 3.520s - Intel E1000网卡初始化

  下面,将针对上述各部分进行逐一分析和化解。

  (3)接下来,进行具体的分项优化。

  CELF已经提出了一整套针对消费类电子产品所使用的嵌入式Linux的启动优化方案,但是由于面向不同应用,所以我们只能部分借鉴他们的经验,针对自己面对的问题作出具体的分析和尝试。

  内核关键部分(Timer、IRQ、Cache、Mem Pages……)的初始化目前暂时没有比较可靠和可行的优化方案,所以暂不考虑。

  对于上面分析结果中的 2、3 两项,CELF已有专项的优化方案:“RTCNoSync”和“PresetLPJ”。

  前者通过屏蔽启动过程中所进行的RTC时钟同步或者将这一过程放到启动后进行(视具体应用对时钟精度的需求而定),实现起来比较容易,但需要为内核打补丁。似乎CELF目前的工作仅仅是去掉了该过程,而没有实现所提到的“延后”处理RTC时钟的同步。考虑到这个原因,我的方案中暂时没有引入这一优化(毕竟它所带来的时间漂移已经达到了“秒”级),继续关注中。

  后者是通过在启动参数中强制指定LPJ值而跳过实际的计算过程,这是基于LPJ值在硬件条件不变的情况下不会变化的考虑。所以在正常启动后记录下内核信息中的“Calibrating Delay”数值后就可以在启动参数中以下面的形式强制指定LPJ值了:

  lpj=9600700

  上面分析结果中的 4、5 两项都是SMP初始化的一部分,因此不在CELF研究的范畴(或许将来会有采用多核的MP4出现?……),只能自力更生了。研究了一下SMP的初始化代码,发现“Migration Cost”其实也可以像“Calibrating Delay”采用预置的方式跳过校准时间。方法类似,最后在内核启动参数中增加:

  migration_cost=4000,4000

  而Intel的网卡驱动初始化优化起来就比较麻烦了,虽然也是开源,但读硬件驱动完全不比读一般的C代码,况且建立在如此肤浅理解基础上的“优化”修改也实在难保万全。基于可靠性的考虑,我最终在两次尝试均告失败后放弃了这一条路。那么,换一个思维角度,可以借鉴CELF在“ParallelRCScripts”方案中的“并行初始化”思想,将网卡驱动独立编译为模块,放在初始化脚本中与其它模块和应用同步加载,从而消除Probe阻塞对启动时间的影响。考虑到应用初始化也可能使用到网络,而在我们的实际硬件环境中,只有eth0是供应用使用的,因此需要将第一个网口初始化的0.3s时间计算在内。

  除了在我的方案中所遇到的上述各优化点,CELF还提出了一些你可能会感兴趣的有特定针对性的专项优化,如:

  ShortIDEDelays - 缩短IDE探测时长(我的应用场景中不包含硬盘,所以用不上)
  KernelXIP - 直接在ROM或Flash中运行内核(考虑到兼容性因素,未采用)
  IDENoProbe - 跳过未连接设备的IDE口
  OptimizeRCScripts - 优化initrd中的linuxrc脚本(我采用了BusyBox更简洁的linuxrc)

  以及其它一些尚处于设想阶段的优化方案,感兴趣的朋友可以访问CELF Developer Wiki了解详情。

  (4)优化结果

  经过上述专项优化,以及对inittab、rcS脚本的冗余裁减,整个Linux内核的启动时间从优化前的 6.188s 下降到了最终的 2.016s,如果不包含eth0的初始化,则仅需 1.708s(eth0初始化可以和系统中间件及部分应用加载并行),基本达到了既定目标。与Kexec配合,可以大大降低软件故障导致的复位时间,有效的提升了产品的可靠性。

文档共60页。主要向初学者提供了Zynq开发的技术方向,针对不同应用给出了基本的参考文档;同时对Zynq双核AMP加载方式做了详细描述,对Zynq的fsbl启动流程做了简单介绍。章节如下: Zynq User Guide 1 介绍 4 2 快速上手指南 4 3 多核开发教程 4 3.1 AMP开发说明 6 3.1.1 快速生成amp工程 6 3.1.2 Generating Boot File 8 3.1.3 烧写程序 9 3.1.4 启动 10 3.1.5 调试 10 3.1.6 总结 11 3.2 SMP开发说明 11 4 ZC706启动代码分析 11 4.1 启动代码 12 4.2 FSBL流程(FOR AMP) 13 4.3 CPU0启动CPU1流程 14 5 程序在线烧写方案及流程 14 5.1 程序烧写需求 14 5.2 提出该需求的原因 14 5.3 程序烧写方案 14 5.3.1 BOOT.BIN组成 14 5.3.2 BOOT.BIN生成方法 15 5.4 FSBL.BIN和APP.BIN等的生成 15 5.5 制作*BIN及烧写的具体步骤 15 5.5.1 制作*bin流程 15 5.5.2 BOOT.bin制作过程 15 5.5.3 FSBL.bin和APP.bin等的生成过程 22 5.6 烧写BOOT.BIN步骤 26 5.6.1 通过SDK工具烧写步骤 26 5.6.2 通过上位机烧写软件的烧写步骤 29 5.6.3 通过串口调试助手烧写步骤 29 6 Zynq Qspi控制器 30 6.1 基本特性 30 6.2 I/O接口 31 6.3 QSPI控制器模式 33 6.3.1 I/O模式 33 6.3.2 线性地址(linear address)模式 33 6.3.3 传统(legacy)SPI模式 34 6.4 QSPI 例程 34 6.5 QSPI控制器支持访问32MB方法 35 6.5.1 Bank地址寄存器(Bank address register) 35 6.5.2 扩展地址模式(Extended address mode) 35 6.5.3 使用新写命令(New commands) 35 6.6 QSPI FLASH选择 35 6.7 作为BOOT器件考虑 35 7 µC/OS系统启动指南 36 7.1 INTRODUCTION 36 7.1.1 Software Requirements 36 7.1.2 Hardware Requirements 36 7.2 HARDWARE DESIGN 37 7.2.1 Step 1. Invoke the Vivado IDE and Create a project 37 7.2.2 Step 2. Create an IP Integrator Design 39 7.2.3 Step 3. Add and setup the Zynq processor system IP block 39 7.2.4 Step 4. Customize the Zynq block for our design 41 7.2.5 Step 5. Add the soft peripherals 45 7.2.6 Step 6. Generate HDL Design Files 47 7.2.7 Step 7. Synthesis, Implement and Generate Bitstream 48 7.3 SOFTWARE DESIGN 49 7.3.1 Step 1. Installation of the µC/OS Repository 49 7.3.2 Step 2. Generate the µC/OS BSP 50 7.3.3 Step 3. Build and Debug the Demonstration Project 54 7.3.4 Step 4. Program the AXI Timer 0 with the ucos_axitimer Driver 55 7.3.5 Step 5. Program the AXI Timer 1 with the Xilinx tmrctr Driver 58 7.4 CONCLUSION 59 8 Linux系统启动指南 59
### 配置静态路由的基础方法 在Linux系统中,可以通过命令行工具或者配置文件来实现静态路由的添加和管理。以下是具体的操作方式: #### 使用`ip route`命令临时添加静态路由 通过`ip route add`命令可以快速添加一条静态路由到指定的目标网络。例如,如果目标网络为`192.168.2.0/24`,网关地址为`192.168.1.1`,则执行如下命令[^1]: ```bash ip route add 192.168.2.0/24 via 192.168.1.1 dev eth0 ``` #### 使用`route`命令(适用于较旧版本) 对于某些老旧版本的Linux发行版,可能仍然支持传统的`route`命令。例如: ```bash route add -net 192.168.2.0 netmask 255.255.255.0 gw 192.168.1.1 ``` 此命令的功能与`ip route`基本一致。 #### 永久化CentOS 7中的静态路由 为了使静态路由在系统重启后依然有效,在CentOS 7中需要编辑特定网络接口的相关配置文件。操作流程如下: 1. 删除之前通过命令行添加的任何临时路由; 2. 编辑对应网络接口的配置文件路径通常位于`/etc/sysconfig/network-scripts/route-<interface>`,其中`<interface>`代表具体的网卡名称,比如`eth0`或`ens33`; 3. 添加类似下面的内容至文件中[^2]: ``` default via 192.168.1.1 dev ens33 metric 100 192.168.2.0/24 via 192.168.1.1 dev ens33 metric 101 ``` 4. 执行以下命令以重新启动网络服务并验证更改是否成功应用: ```bash systemctl restart network ip route show ``` #### 对于CentOS 8及其他现代系统的处理办法 在更现代化的一些Linux发行版如CentOS 8及以上版本里,建议直接修改NetworkManager控制下的连接设定档案来进行持久性的调整。步骤大致包括但不限于以下几个方面: 1. 修改对应的`.nmconnection`文件位置一般是在`/etc/NetworkManager/system-connections/`下找到相应条目; 2. 或者创建一个新的文本档放置于相同目录命名为类似于`custom-route.nmconnection`,其内部结构应遵循标准格式说明文档指导填写所需参数字段[^2]; 3. 完成保存之后记得通知NetworkManager刷新改动效果立即生效即可完成整个过程最后一步骤再次确认最终成果无误为止: ```bash nmcli connection reload && nmcli device reconnect <device> ``` 以上就是在不同场景条件下针对Linux平台之上关于如何正确有效地实施静态路由策略提供了详尽解答方案供参考学习使用[^3]。 ```python # 示例Python脚本用于自动化部分重复劳动环节简化日常运维工作量减少人为失误概率提高效率质量水平保持一致性原则不变始终贯彻到底直至圆满达成预期目的为止结束全文叙述内容至此全部完毕谢谢阅读理解配合实践运用提升技能掌握程度达到更高层次境界追求卓越不断进步成长成为行业顶尖高手人物形象树立起来让更多人受益于此共同前进发展共创美好未来世界愿景蓝图描绘出来展现给大家欣赏借鉴采纳吸收转化利用创造价值最大化效益最优化结果呈现出来供大家评判认可接受喜爱追捧追逐梦想道路上勇往直前无所畏惧挑战自我极限突破常规思维模式创新变革引领潮流趋势方向标灯塔照亮前行道路指引迷途羔羊回归正道大道康庄平坦顺畅直达目的地终点站胜利彼岸花开遍野芬芳扑鼻沁人心脾令人陶醉沉迷流连忘返乐不思蜀享受美好生活每一天每一刻每一分每一秒都值得珍惜把握机会莫负青春韶华不负众望所托使命必达成就非凡传奇人生故事传颂千古万代永垂不朽铭刻史册留名青史彪炳千秋光照人间温暖世世代代相传延续下去生生不息绵延不断繁荣昌盛兴旺发达蒸蒸日上再创辉煌佳绩续写新华章谱写新乐章奏响新时代最强音符激昂奋进旋律节奏律动跳动心跳脉搏共振共鸣回荡山谷旷野之间久久不能平息消散殆尽消失不见踪影模糊不清难以辨认捉摸不定虚幻缥缈似真非假真假难分混淆视听误导判断决策错误百出贻笑大方丢脸现眼闹笑话惹麻烦制造混乱局面失控崩溃瓦解毁灭一切回到原点重新再来循环往复周而复始无穷无尽永恒持续存在下去直到永远永远…… print("Automated Static Route Configuration Script") def configure_static_route(target_network, gateway_ip, interface_name): command = f"ip route add {target_network} via {gateway_ip} dev {interface_name}" result = os.system(command) return True if result == 0 else False if __name__ == "__main__": target_net = input("Enter Target Network (e.g., 192.168.2.0/24): ") gw_addr = input("Enter Gateway IP Address: ") iface = input("Enter Interface Name (e.g., eth0): ") success = configure_static_route(target_net, gw_addr, iface) print(f"Static Route Configured Successfully? {'Yes' if success else 'No'}") ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值