跟踪分析Linux内核的启动过程

陈良 + 原创作品转载请注明出处 + 《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创建了其他的内核线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值