分类: LINUX
2018-04-10 17:38:34
较为简单可行的方式是通过PrintkTime功能为启动过程的所有内核信息增加时间戳,便于汇总分析。PrintkTime最早为CELF所提供的一个内核补丁,在后来的Kernel 2.6.11版本中正式纳入标准内核。
开启PrintkTime功能的方法很简单,只需在内核启动参数中增加“time”即可。当然,你也可以选择在编译内核时直接指定“Kernel
hacking”中的“Show timing information on printks”来强制每次启动均为内核信息增加时间戳
Kernel hacking --->
printk and dmesg options --->
[*] Show timing information on printks │ │
│ │ (4) Default message log level (1-7)
///////////////////////////////////////////////////////
CPU Power Management --->
CPU Frequency scaling --->
Default CPUFreq governor (performance) --->
(X) performance
( ) powersave
( ) userspace
( ) ondemand
( ) conservative
( ) interactive
////////////////////////////////////////////////////
这部分分为三部:
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,将无用模块搬入文件系统启动。(类似于延时启动)
linux4.15内核如下
linux内核 init/main.c
static void __init do_initcall_level(int level)
{
initcall_t *fn;
strcpy(initcall_command_line, saved_command_line);
parse_args(initcall_level_names[level],
initcall_command_line, __start___param,
__stop___param - __start___param,
level, level,
&repair_env_string);
for (fn = initcall_levels[level]; fn < initcall_levels[level+1]; fn++)
{
/*printk("======M:fn%p=====\n",fn);*/
do_one_initcall(*fn);
}
}
static void __init do_initcalls(void)
{
int level;
for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
{
/*printk("=====Level:%d=====\n",level);*/
do_initcall_level(level);
}
}
串口输出结果里
[ 0.347538] ======M:fn80745924=====
[ 0.348311] 2020000.serial: ttymxc0 at MMIO 0x2020000 (irq = 19, base_baud = 5000000) is a IMX
[ 1.727805] console [ttymxc0] enabled
[ 1.733490] 21e8000.serial: ttymxc1 at MMIO 0x21e8000 (irq = 234, base_baud = 5000000) is a IMX
[ 1.743330] ======M:fn80745928=====
linux4.1.15_imx6]$ vim System.map
80745924 t __initcall_imx_serial_init6
这个fn80745924占用时间挺长。
可以找到是如下这个模块
drivers/tty/serial/imx.c:static int __init imx_serial_init(void)
drivers/tty/serial/imx.c:module_init(imx_serial_init);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////