概述
陈良 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://www.xuetangx.com/courses/course-v1:ustcX+USTC001+_/about
1. 调试gdb
(1)运行qemu
(2)运行gdb并链接remote
(3)设置断点break start_kernel,break rest_init
2. 分析start_kernel
在断点处停止:
分析start_kernel
asmlinkage __visible void __init start_kernel(void)
函数中最后一行调用
rest_init();
进入rest_init()
393static noinline void __init_refok rest_init(void)
394{
395 int pid;
396
397 rcu_scheduler_starting();
398 /*
399 * We need to spawn init first so that it obtains pid 1, however
400 * the init task will end up wanting to create kthreads, which, if
401 * we schedule it before we create kthreadd, will OOPS.
402 */
403 kernel_thread(kernel_init, NULL, CLONE_FS); //kernel_init启动1号进程
404 numa_default_policy();
405 pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES); //kthreadd创建了其他的内核线程
406 rcu_read_lock();
407 kthreadd_task = find_task_by_pid_ns(pid, &init_pid_ns);
408 rcu_read_unlock();
409 complete(&kthreadd_done);
410
411 /*
412 * The boot idle thread must execute schedule()
413 * at least once to get things moving:
414 */
415 init_idle_bootup_task(current);
416 schedule_preempt_disabled();
417 /* Call into cpu_idle with preempt disabled */
418 cpu_startup_entry(CPUHP_ONLINE); //调用cpu_idle_loop
419}
查看cpu_startup_entry
256void cpu_startup_entry(enum cpuhp_state state)
257{
258 /*
259 * This #ifdef needs to die, but it's too late in the cycle to
260 * make this generic (arm and sh have never invoked the canary
261 * init for the non boot cpus!). Will be fixed in 3.11
262 */
263#ifdef CONFIG_X86
264 /*
265 * If we're the non-boot CPU, nothing set the stack canary up
266 * for us. The boot CPU already has it initialized but no harm
267 * in doing it again. This is a good place for updating it, as
268 * we wont ever return from this function (so the invalid
269 * canaries already on the stack wont ever trigger).
270 */
271 boot_init_stack_canary();
272#endif
273 arch_cpu_idle_prepare();
274 cpu_idle_loop(); //此处调用零号进程
275}
进入cpu_idle_loop查看
189static void cpu_idle_loop(void)
190{
191 while (1) {
192 /*
193 * If the arch has a polling bit, we maintain an invariant:
194 *
195 * Our polling bit is clear if we're not scheduled (i.e. if
196 * rq->curr != rq->idle). This means that, if rq->idle has
197 * the polling bit set, then setting need_resched is
198 * guaranteed to cause the cpu to reschedule.
199 */
200
201 __current_set_polling();
202 tick_nohz_idle_enter();
203
204 while (!need_resched()) {
205 check_pgt_cache();
206 rmb();
207
208 if (cpu_is_offline(smp_processor_id()))
209 arch_cpu_idle_dead();
210
211 local_irq_disable();
212 arch_cpu_idle_enter();
213
214
223 if (cpu_idle_force_poll || tick_check_broadcast_expired())
224 cpu_idle_poll();
225 else
226 cpuidle_idle_call();
227
228 arch_cpu_idle_exit();
229 }
230
239 preempt_set_need_resched();
240 tick_nohz_idle_exit();
241 __current_clr_polling();
242
249 smp_mb__after_atomic();
250
251 sched_ttwu_pending();
252 schedule_preempt_disabled();
253 }
254}
在cpu_idle_loop中while(1)一直循环,作为零号进程等待新的进程的创建
3. 总结
Linux内核的启动过程就是:
start_kernel启动,调用rest_init函数,生成零号进程并一直循环执行;
零号进程中又通过kernel_init创建了一号进程,并通过kthread创建了其他的内核线程。
最后
以上就是标致冷风为你收集整理的跟踪分析Linux内核的启动过程的全部内容,希望文章能够帮你解决跟踪分析Linux内核的启动过程所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复