平台:Xilinx Zynq SoC上的ARM Cortex A9上的Linux。
我问了一个问题: 为什么内核启动太晚了
基本上我试图理解,然后最小化这两个事件之间的延迟:
[Sat Apr 12 19:33:50.692 2014] Starting kernel ... [Sat Apr 12 19:33:50.692 2014] [Sat Apr 12 19:33:51.298 2014] Booting Linux on physical CPU 0x0
第一行告诉控件现在正在给内核,而第二行告诉控件现在是内核并且正在由CPU执行。
从u-boot到内核的这种切换对我们的应用程序来说花费了太多时间。
为了理解这两个事件之间发生了什么,我在下面插入了printf语句:
1- bootm.c
我把以下行放在函数static void boot_jump_linux(bootm_headers_t *images, int flag)
} if (!fake) {printf("above kernel_entry in boot_jump_linux in bootm.cn"); kernel_entry(0, machid, r2); printf("below kernel_entry boot_jump_linux in bootm.cn"); } }
2- main.c
我把这样的声明放在start_kernel
函数中:
asmlinkage void __init start_kernel(void) { printk("I am the first statement in start_kernel in main.c" ); char * command_line; extern const struct kernel_param __start___param[], __stop___param[];
然后我编译了u-boot和内核,新的日志消息包含以下行:
[Sat Apr 12 19:33:50.692 2014] Starting kernel ... [Sat Apr 12 19:33:50.692 2014] above kernel_entry in boot_jump_linux in bootm.c [Sat Apr 12 19:33:51.298 2014] I am the first statement in start_kernel in main.c [Sat Apr 12 19:33:51.298 2014] Booting Linux on physical CPU 0x0
(实际上我把printf语句放在很多地方但是所有的thsoe都在“启动内核……”或“在物理CPU 0x0上启动Linux”之下,所以我在这个讨论中忽略它。我也用ftrace来看热点,但它没有报告u-bootfunction)。
我观察到“bootm.c中boot_jump_linux中的kernel_entry下面”永远不会打印在日志消息中的任何地方。 这表明在函数kernel_entry(0,machid,r2)之后控件不会返回; 之所以被调用,是因为linux现在已经控制并正在执行。
所以我的目标是知道在这两个事件中正在执行哪个function。
现在要了解发生了什么(即使在插入我的printf / printk消息后仍未清楚)我问了以下问题:
1- 在u-boot中,kernel_entry指向哪个函数?
2- 试图理解函数指针的用法
基于那里的答案,我怀疑我的热点,即花费很多时间的代码位于以下文件之一:
1- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/kernel/head.S
2- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/kernel/head-common.S
3- https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/compressed/head.S
我的问题:
1-我的理解是否正确,我应该专注于上述文件?
2-调用kernel_entry(0, machid, r2);
是的,控件转到上面的代码和哪一行?
我怀疑文件https://github.com/Xilinx/linux-xlnx/blob/master/arch/arm/boot/compressed/head.S对我没用,因为这是解压缩所必需的,但是我的内核已解压缩,因为在u-boot日志中可以很早地看到以下行:
[Sat Apr 12 19:33:50.596 2014] Uncompressing Kernel Image ... OK
完整的日志在这里 。
有人可以在这方面让我高兴吗?
提前谢谢了!!
我的目标是尽可能快地进行切换。
你认为使用早期的printk我可以更快地启动,因为切换会提前吗?
您的问题以及计算“快速”或“延迟”的方法都是基于有缺陷的数据。
您认为0.5秒“延迟”实际上是U-Boot 实时输出“Starting kernel …” ,而内核缓冲并推迟输出其“Booting Linux”直到系统和控制台初始化。 这是将苹果与橙子进行比较。
至少你必须通过启用早期的printk来实时输出内核(就像U-Boot一样)。 然后您的时间戳将更好地指示实际经过的时间。
Linux内核映射第18章的摘录(由我强调):
在printk()的坚固性的盔甲中存在一个缝隙。 在控制台初始化之前,它在内核引导过程中的某个点之前是不可用的。 实际上,如果控制台没有初始化,输出应该在哪里?
这通常不是问题,除非您在引导过程中很早就调试问题(例如,在setup_arch()中执行特定于体系结构的初始化)。 这样的调试是一个挑战,并且没有任何类型的打印方法只会使问题复杂化。
有一些希望,但不是很多。 硬核架构黑客使用可以工作的硬件(比如串口)与外界进行通信。 相信我这对大多数人来说并不好玩。 一些受支持的架构确实实现了一个理智的解决方案,然而其他(包括i386)有可用的补丁,也节省了一天。
解决方案是一个printk()变体,可以在引导过程的早期输出到控制台:early_printk()。 行为与printk()相同,只更改名称及其先前工作的能力。 然而,这不是可移植的解决方案,因为并非所有支持的体系结构都实现了这样的方法。 它可能会成为你最好的朋友,如果它确实如此。
有关启用早期printk的详细信息,请参阅相同问题的答案 (由您的双胞胎?)。
所以不,使用早期的printk不会改善“切换”或整体启动时间。
但它应该有助于防止你寻找幻像障碍。
我想知道怎么会发生。
您正在通过指向其他函数的函数指针显示直接函数调用。
我没有看到除了中断代码之外的任何东西都会干扰它。
所花费的时间是600毫秒,这并不是很多,但当然在很多情况下都很明显(特别是在Zynq相关的地方)。
要调查的事情:
以上就是c/c++开发分享如何优化U-boot到内核切换代码?相关内容,想了解更多C/C++开发(异常处理)及C/C++游戏开发关注计算机技术网(www.ctvol.com)!)。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/523239.html