1. 首先设置断点在start_kernel函数处,使用c命令之后提示进入了该启动函数,如图:
图
2. 进入函数之后发现这里面的大多数函数并不能从名字上看出它们的意义,只能一步一步的试,于是我在init_task这个重要的进程变量处设置断点b 510
,然后c,发现menuOS竟然开始跑了。但是结果却不尽如意,因为它最终没有成功的启动系统,而是卡死在这一步,于是ctrl+c
中断操作,得到了如下信息。
default_idle () at arch/x86/kernel/process.c:314
314 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT,,smp_processor_id());
于是我去查看了arch/x86/kernel/process.c:314
:
310 void default_idle(void)
311 {
312 trace_cpu_idle_rcuidle(1, smp_processor_id());
313 safe_halt();
314 trace_cpu_idle_rcuidle(PWR_EVENT_EXIT,smp_processor_id());
315 }
看完之后一头雾水,本打算放弃,我看到了在main.c:511
中的smp_setup_processor_id()
查阅得知,此函数是针对SMP处理器,用于获取当前CPU的硬件ID,如果不是多核,函数为空。判断是否定义了CONFIG_SMP,如果定义了,调用read_cpuid_mpidr读取寄存器CPUID_MPIDR的值,即当前正在执行初始化的CPU ID结合刚才qemu中给出的信息unable to init device /dev/mcelog
,猜想应该是start_kernel函数在初始化0号进程的时候无法识别cpu的硬件ID从而报错导致卡死。那如何来验证自己的猜想呢?
- 1.
查看/dev/mcelog
。在自己的系统上查看发现这是个c
属性文件,即字符设备,查阅得知,该设备是用于是 x86 的 Linux 系统上用来 检查硬件错误,特别是内存和CPU错误的工具。 - 2.查阅有关
smp_processor_id()
的资料,发现这个函数不同于smp_setup_processor_id()
函数,它不可以直接读取寄存器中的值来获取cpuid,而必须获取内核变量保存的处理器id,因此smp_processor_id()
函数必须使用初始化函数。
这大概便是为何刚才初始化0进程时出错的原因了,但是苦于找不到上述两个函数的源码,找到了也不一定能看懂,只能粗略分析至此。