魏昊卿——《Linux内核分析》第三周作业:Linux系统启动过程
一、实验部分
实验指导
- 使用实验楼的虚拟机打开shell
1 cd LinuxKernel/ 2 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
内核启动完成后进入menu程序(《软件工程C编码实践篇》的课程项目),支持三个命令help、version和quit,您也可以添加更多的命令,对选修过《软件工程C编码实践篇》的童鞋应该是a piece of cake.
- 使用gdb跟踪调试内核
1 qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S # 关于-s和-S选项的说明: 2 # -S freeze CPU at startup (use ’c’ to start execution) 3 # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
- 另开一个shell窗口
1 gdb 2 (gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表 3 (gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行 4 (gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后
实验截图:
二、分析start_kernel函数的执行进程
从start_kernel函数开始,内核进入了C语言部分,它完成了内核的大部分初始化工作,类似于一般可执行程序中的主函数main。
主要函数分析:
1.set_task_stack_end_magic(&init_task)
init_task为一个全局变量,相当于mykernel中0号进程的pcb。
2.trap_init()
初始化中断向量,设置了很多中断门、硬件中断。其中set_system_trap_gate(SYSCALL_VECTOR)处理系统调用,用指令的方式触发一个中断。
3.sched_init()
调度模块的初始化
4.rest_init()->kernel_thread(kernel_init,...)->kernel_init->run_init_process
linux中的1号进程,第一个用户态进程,根目录下默认的进程
rest_init()->kernel_thread(kthreadd,...)
用一个内核线程来管理系统的一些资源
5..rest_init()->cpu_startup_entry()->cpu_idle_loop()
一直循环,当系统没有进程需要执行的时候就调度idle进程,从内核启动开始一直存在,0号进程。0号进程创建了1号进程,并且还创建了内核中其他的一些服务线程。
三、总结
这周学习了linux内核的启动过程,并分析了其中几个需要重点掌握得函数。linux内核启动的过程就是在为进程以及进程调度做准备,在rest_init()函数之前的所有代码都是在为进程的出现进行初始化工作,直到rest_init()出现,进程才得以出现。此后0号进程一直存在,并由此产生1号进程等之后的进程,当系统没有进程需要执行的时候就调度idle进程。
魏昊卿 原创作品转载请注明出处 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000