|
介绍
我们提供的Linux系统功能比较丰富,但某些用户产品的特定场合,对时间系统的启动时间有一定的要求,有些功能并不是必要,那么就需要对系统进行优化,本教程将介绍如何对我公司的AM335x系列产品进行时间优化。
打开内核时间戳
在调试间断,评估时间应打开一些时间信息帮助分析,在调试之后再关闭。
[mw_shl_code=bash,false]$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig [/mw_shl_code]
[mw_shl_code=bash,false] Kernel hacking --->
Show timing information on printks[/mw_shl_code]
重新编译内核之后,在启动时内核的每行打印信息前面都会显示一个像这样的时间:
[ 0.000000] Console: colour dummy device 80x30
[ 0.000188] Calibrating delay loop... 795.44 BogoMIPS (lpj=3977216)
[ 0.087383] pid_max: default: 32768 minimum: 301
[ 0.087497] Security Framework initialized
[ 0.087594] Mount-cache hash table entries: 512
[ 0.087971] CPU: Testing write buffer coherency: ok
解启动阶段
重新编译内核之后Linux系统启动会依次进行MLO、U-boot、Kernel、Filesystem等几个阶段的运行。如何从打印信息区分所处的时哪个阶段呢,可以用如下的打印字段来查找。
MLO:当出现第一行字符时,MLO就开始执行了。
Bootloader:当显示“U-Boot 2011.09-svn18 (Dec 25 2014 - 14:20:57)”时,则Bootloader已开始执行。
Kernel: 当显示“Uncompressing Linux... done, booting the kernel. ”时,则Linux Kernel已开始执行。
Filesystem:当第一条没有方括号Linux时间戳的打印信息显示时,即说明不是内核输出的信息,那么这是文件系统开始初始化。
Kernel启动实时性分析
利用Kernel的时间戳,我们可以分析内核的启动情况,下图是MYD-AM335X在没有优化过的内核启动时间统计图。完整的统计图可下载附件。
从图中我们可以看到,时间从左至右,内核启动总共耗时约6.4秒,其中占比例最大的三款青色,宝绿色,暗灰蓝色分别是
serial_omap_init:串口初始化,用时约0.7秒。初始化的串口数比较多,如果你不需要那么多的串口,可以裁剪这里加快初始化时间。
omap_nand_init:Nand初始化,用时约0.55秒。NAND的初始化速度会受到存储设备IO的影响,可以考虑使用速度更快的存储器进行优化。
ubi_init:UBI文件系统初始化,用时约2.28秒。UBI文件系统的初始化,可以通过减小文件系统容量的方法,来加快文件系统加载以及执行初始化的速度。如何裁剪文件系统的容量以及启动优化启动脚本,请点击这里(查看我后续的的教程coming soon)
其他可进行优化的地方
关闭内核校验
默认的,U-boot加载内核时会对读取的内核数据进行校验,如下所示
[mw_shl_code=bash,false] Entry Point: 80008000
Verifying Checksum ... OK
XIP Kernel Image ... OK[/mw_shl_code]
如果在判断校验失败后,没有任何应对措施的话,那么校验就是浪费时间而已,所以如果你没有修复措施,建议禁用内核的校验,关闭需要修改两个地方:
1)在命令行或环境变量中将verify保存为n
[mw_shl_code=bash,true]setenv verify n[/mw_shl_code]
2)修改U-boot代码 /common/cmd_bootm.c
[mw_shl_code=c,true] - images.verify = getenv_yesno ("verify");
+// images.verify = getenv_yesno ("verify");
+ images.verify = 0;[/mw_shl_code]
取消U-boot延时
U-boot启动时会出现读秒,并提示按任意键中断启动的字样。如果最终产品不需要操作U-boot命令行,这也是浪费时间的。
在U-boot命令行或环境变量中将bootdelay保存为0
[mw_shl_code=bash,true]setenv Bootdelay 0[/mw_shl_code]
U-boot环境变量内容
为了通用性和开发便捷,我们提供的U-boot环境变量文本比较大,但一般最终产品之后用到其中的一部分,那么读取将会耗费多余的时间,可减小文本内容以加快读取的速度。
如果不需要IP,在U-boot环境变量中将ip=off,还可以用mem=参数减小需要初始化的内存容量,加快速度。
移除不适用的外设模块
如果在MLO中不使用NAND Flash和OneNAND
[mw_shl_code=c,false]#undef CFG_NAND
#undef CFG_ONENAND[/mw_shl_code]
如果在MLO中不使用MMC/SD
[mw_shl_code=c,false]#undef CONFIG_MMC
#undef CFG_CMD_MMC
#undef CFG_CMD_FAT
#undef CONFIG_DOS_PARTITION[/mw_shl_code]
如果在U-boot中不需要帮助信息
[mw_shl_code=c,false]#undef CONFIG_SYS_LONGHELP[/mw_shl_code]
如果在U-boot中不需要USB
[mw_shl_code=c,false]#undef CONFIG_USB_OMAP3
#undef CONFIG_MUSB_HCD
#undef CONFIG_MUSB_UDC[/mw_shl_code]
如果在U-boot中不需要网络
[mw_shl_code=c,false]#undef CONFIG_CMD_NET[/mw_shl_code]
内核模块加载,延迟初始化
有些不是很常用的驱动,我们可以将其选中编译为模块,在使用时在将其insmod进来。
还有一种是在启动后不会马上使用的模块,可以使用延迟初始话的方法,使Linux先尽快跑起来,之后再加载设置为延迟启动的功能。
设置延迟初始化的方法为将内核代码中的
[mw_shl_code=c,false]--module_init() [/mw_shl_code]
修改为
[mw_shl_code=c,false]++deferred_module_init() [/mw_shl_code]
然后在启动启动之后使用如下命令手动开启
[mw_shl_code=bash,false]$ echo 1 >/proc/deferred_initcalls[/mw_shl_code]
详细教程可参考:http://elinux.org/Deferred_Initcalls
Release最终版本优化
在默认配置中,引导加载程序和Linux内核串行控制台打印许多详细的消息。 虽然在开发阶段非常有用,这些消息不需要最终的产品。 根据打印的数量,关掉这些消息可以节省1 - 2秒的整体引导过程。方法如下:
MLO:
[mw_shl_code=c,false]# undef CFG_PRINTF[/mw_shl_code]
U-boot:
先U-boot代码中定义:
[mw_shl_code=c,false]#define CONFIG_SILENT_CONSOLE 1[/mw_shl_code]
再将以下参数保存到环境变量:
[mw_shl_code=bash,false] set silent 1
saveenv[/mw_shl_code]
Kernel:
将“quiet“传递到内核的command-line中
gcc:
在所有的Relase编译中删除-g参数,来禁用gdbg调试功能。
|
|