kernel启动优化
作者:printk 发布于:2015-4-30 8:42
抛砖引玉,手有余香
由于老衲技术水平有限,以下梦话可能会有很多漏洞,希望各位大拿发现bug后,以强大的知识理论碾压老衲,让贫僧能在痛苦中疯狂成长。
---------------------------------------------------->\n
由于老衲最近在做车载linux kernel优化,特别是对启动时间的优化,从一开始的漫无目的,到现在的算是了解的过程,下了很大功夫。
特别是优化到最后2s以内,每10ms的优化太让人吐血了。杂话不多说,开整。
工欲善其事,必先利其器。
要调整启动时间,肯定得需要一个比较精确的时间戳,常用的有直接在kernel的menuconfig中选中printk_time,这样每条log前面都会打出相应的时间。这个就可以直接在menuconfig中配置,比较方便。但是精度不太高,因为选中printk_time也会影响启动时间。
这里推荐使用ckermit,直接嵌套minicom,配置完了之后可以将log重定向到一个文件中,在文件中对每条log就有详细的时间戳。
ubuntu系统直接sudo apt-get install ckemit
vim ~/.kermrc
set line /dev/ttyUSB0 #配置dbug串口
set speed 115200 #配置dbug uart速率
set carrier-watch off #
set handshake none
set flow-control none # 配置硬件流控
robust
set file type bin
set file name lit
set rec pack 1000
set send pack 10000
set windows 5
set protocol xmodem
set protocol zmodem
set session-log TIMESTAMPED-TEXT # 配置log重定向格式
log session #将log写入文件session中,此文件位于~/session
connect #自动链接串口,如果不写这条命令,需在进入ckermit 命令行后输入 c 或 connect
:wq! #保存退出
执行 sudo kermit
进入ckermit并自动链接串口,ps:如果想从串口退出 按下 "Ctrl + \" 并输入 “q”
工具配置好后,放下,开始分析从哪优化
三军未动,粮草先行
kernel启动分为三部分
uboot引导 -> kernel载入启动 -> 挂载文件系统(跑初始化脚本)
1.uboot启动
对uboot不是很了解,希望有懂的大拿能协助我完成这部分内容。对这部分只是有点想法
首先,去除万恶的bootdelay,这部分最低也是1s。其次,去除不必要的在uboot部分启动的驱动,加入MMU(别问我为什么,关于加MMU这部分是另一位大神告诉我的,据说很有用,此处也希望各位大拿协助),跳过kernel的头部信息0-4k,直接从kernel的主启动部分down入内存。
首先要了解uboot是如何将kernel down入到内存中,根据硬件不同,uboot的配置也不同,但是优化点大同小异,本人使用的硬件平台如下
norflash:16m 放置uboot与kernel
emmc:4g 放置文件系统
Arm Cortex-A9架构的freescale imx6系列
所以在我的板子上,uboot需要将uImage从norflash中down入ram中。
那么,优化点来了。。。
拷贝数据肯定要用到memcpy,memset,特别是uImage还是比较大的(我裁剪完有2.9M),能将memcpy与memset的运行速度优化了,会直接减少启动时间,这里是用汇编写了一个memcpy 与 memset,众所周知,汇编的执行效率要大于C。此处大概优化几毫秒(这个地方是从2s 优化到 1.3s的过程中考虑到的。。)
2.kernel启动
首先uImage会有一个解压缩的过程,在编译的时候,会对uImage配置一个压缩算法,常用的有bz2,gzip,lzop,(貌似现在已经不支持bz2了)那么通过对比这几种压缩算法,找出一款最适合自己的。。。
Alogrithm % remaining MB/s Encoding MB/s Decoding
gzip 13.4 21 %2
lzop 20.5 135 410
bz2 XX XX XX
由于历史悠久,老衲已经忘却了bz2的压缩信息,不过确是与gzip差不多
那么由此看出,最适合老衲的就是lzop,因为空间大小完全不用考虑,很足够,但是解压速率是gzip的四倍不到,已经很快了。
其次就是lpj 熟悉的人一看见他就有种跳过的冲动,这货就是kernel启动时,check一下子,没什么用,只要前期都ok了,这部分就是skip用的
关于lpj的值,可以通过打log去判断,每一个硬件环境,lpj的值基本不同。
以上都是小点,little point, 其实占用时间最长的 就是 启动kernel时 加载各个模块,跑各个probe所占用的时间
这部分分为三部:
1)内核裁剪,将用不着的模块干掉。
2)优化所需build-in的启动时间
这里需要详细说一下,有个技巧,就是在kernel目录下的 init/main.c中 do_initcalls函数中
static void __init do_initcalls(void)
{
initcall_t *fn;
for (fn = __early_initcall_end; fn < __initcall_end; fn++){
// printk("==========================now will call : %p\n",fn);
do_one_initcall(*fn);
}
}
将printk那行打开即可。
这里会调到所有注册在module_init段中的函数
换句话说就是你需要编译的module都会在这调用。那么就会很方便的 查看出哪个模块占用多少时间。从而去针对性的优化。
其他的 都是一些简单的,比如说优化log等级,优化开机logo,将无用模块搬入文件系统启动。(类似于延时启动)
3.文件系统优化
水太深,老衲用的还是比较旧的
由于各个文件系统不同,启动sequence也不一样。业内公认启动最快的是systemd,因为这货竟然是并发启动。
由于板子不同,需求不同,所以每个不同的系统的优化肯定有很多不同之处
希望大家多多讨论,将我没有 涉及到的,或者优化的不对的地方翻出来,一起研究研究。
以上。

评论:
2015-10-30 19:58
更意外的是通过其他文章的评论里wowo的链接看到这篇文章后,我才发现原来之前来过这里,只是当时错过了~
以后常来,向大家学习!
2015-06-23 16:53
还有个疑问:把kernel读出来 vs 解压kernel, 更大的kernel读出来的时间肯定更长,优化这个时间 vs 优化解压的时间,哪个更好,要对比一下吧?
就uboot来说,我感觉主要有两个功能,一个是把kernel拷贝到内存,另一个是调试。 在发布的时候,其实调试功能是不需要的,仅需要第一个功能。
firstboot也是可以把kernel拷贝到内存的,这样发布的时候就可以不要uboot了。
ps:
1、firstboot是指把uboot拷贝到内存的这个boot,imx6中可能不是这个名字。
2、建议楼主说明你优化的kernel和uboot版本。 kernel 3.0以上版本,大多用了设备树,uboot具有调试设备树的功能,所以uboot有可能悄悄改了设备树,如果不要uboot,需要确定uboot是如何改了设备树。
3、uboot一般是读取固定大小的kernel和文件系统进内存。例如kernel是2.9M,uboot可能固定读4M,不会去管真正的kernel是多大,建议楼主确认下你的uboot是否是这样。
还有两个记不清楚的地方,说出来供楼主参考。
我以前粗略看过kernel的汇编部分,记得在汇编里好像会把真正的kernel搬运到新的内存地址,这个地方应该也可以优化。
读内核时,开启dma,应该可以读的更快吧
2015-05-07 17:59
我们用的CPU是AMD Geode LX800,在车载方面,和大师用的A9哪个性能更好?
2015-05-18 15:08
我们单位是一个老牌车载导航日企,名字不方便透露,抱歉!
2015-05-04 16:00
1. 关于时间戳,依赖打印,总是不精确的。可以在启动的第一时间,start一个硬件timer,在后续的时间点中,通过timer的计时,精确获取耗时信息。
2. 到底要统计哪些过程的耗时,是需要经过仔细思考设计的。其实几个点就够了,目的性要强。
3. 最重要的,是要找出关键步骤的耗时(可能你已经找出来,但没有给大家贴下来哦)。
4. 关于u-boot,还是要搞清楚的,实在不行,就不用它了呗,自己写个。
5. kernel在norflash中,可以考虑加载和解压,哪个更耗时。说不定使用Image会更快(说不定)。
功能
最新评论
- wangjing
写得太好了 - wangjing
写得太好了! - DRAM
圖面都沒辦法顯示出來好像掛點了。 - Simbr
bus至少是不是还有个subsystem? - troy
@testtest:只要ldrex-modify-strex... - gh
Linux 内核在 sparse 内存模型基础上实现了vme...
文章分类
随机文章
文章存档
- 2025年4月(5)
- 2024年2月(1)
- 2023年5月(1)
- 2022年10月(1)
- 2022年8月(1)
- 2022年6月(1)
- 2022年5月(1)
- 2022年4月(2)
- 2022年2月(2)
- 2021年12月(1)
- 2021年11月(5)
- 2021年7月(1)
- 2021年6月(1)
- 2021年5月(3)
- 2020年3月(3)
- 2020年2月(2)
- 2020年1月(3)
- 2019年12月(3)
- 2019年5月(4)
- 2019年3月(1)
- 2019年1月(3)
- 2018年12月(2)
- 2018年11月(1)
- 2018年10月(2)
- 2018年8月(1)
- 2018年6月(1)
- 2018年5月(1)
- 2018年4月(7)
- 2018年2月(4)
- 2018年1月(5)
- 2017年12月(2)
- 2017年11月(2)
- 2017年10月(1)
- 2017年9月(5)
- 2017年8月(4)
- 2017年7月(4)
- 2017年6月(3)
- 2017年5月(3)
- 2017年4月(1)
- 2017年3月(8)
- 2017年2月(6)
- 2017年1月(5)
- 2016年12月(6)
- 2016年11月(11)
- 2016年10月(9)
- 2016年9月(6)
- 2016年8月(9)
- 2016年7月(5)
- 2016年6月(8)
- 2016年5月(8)
- 2016年4月(7)
- 2016年3月(5)
- 2016年2月(5)
- 2016年1月(6)
- 2015年12月(6)
- 2015年11月(9)
- 2015年10月(9)
- 2015年9月(4)
- 2015年8月(3)
- 2015年7月(7)
- 2015年6月(3)
- 2015年5月(6)
- 2015年4月(9)
- 2015年3月(9)
- 2015年2月(6)
- 2015年1月(6)
- 2014年12月(17)
- 2014年11月(8)
- 2014年10月(9)
- 2014年9月(7)
- 2014年8月(12)
- 2014年7月(6)
- 2014年6月(6)
- 2014年5月(9)
- 2014年4月(9)
- 2014年3月(7)
- 2014年2月(3)
- 2014年1月(4)
2016-04-01 20:48