2020-2021-1 20209321 《Linux内核原理与分析》第四周作业

MenuOs的构造

1.跟踪调试Linux内核的启动过程

2.从start_kernel到init进程启动的过程分析

3.总结

1.跟踪调试Linux内核的启动过程

  • 启动MenuOS

输入命令:

$ cd LinuxKernel/

$ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img

  • 跟踪调试Linux内核的启动过程
    $ qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S

  • 再打开一个窗口,水平分割,启动gdb,把内核加载进来,建立连接。

打开gdb调试器
$ gdb

在gdb中输入以下命令:

在gdb界面中targe remote之前加载符号表:
(gdb)file linux-3.18.6/vmlinux

建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行:
(gdb)target remote:1234

断点的设置可以在target remote之前,也可以在之后:
(gdb)break start_kernel

在start_kernel处设置断点,刚才是stop状态,如果按c继续执行,那么系统开始启动执行,启动到start_kernel函数的位置停在断点处

再设置一个断点rest_init,继续执行,停在断点处。

2.从start_kernel到init进程启动的过程分析

init目录中的main.c源文件是整个Linux内核启动的起点,但它的起点不是main函数,而是start_kernel函数,start_kernel函数是初始化Linux内核启动的起点,start_kernel函数几乎涉及了内核的所有主要模块,如中断向量的初始化,内存管理的初始化,调度模块的初始化等。start_kernel前的代码使用汇编语言来进行硬件的初始化,为C代码的运行设置环境。Linux在无进程概念的情况下将一直从初始化部分的代码执行到start_kernel,然后再到其最后一个函数调用rest_init。从rest_init开始,Linux开始产生进程,init_task是0号进程,但它不是系统通过kernel_thread的方式创建的,init_task创建了1号内核进程kernel_init后,调用cpu_idle()演变成了idle进程,执行一次调度后,init内核进程运行,1号内核进程负责执行内核的部分初始化工作及进行系统配置,最后调用do_execve加载init程序,演变成init进程(用户态1号进程),init进程是内核启动的第一个用户态进程,是其它用户进程的祖先进程。init_task调用kernel_thread创建2号内核线程,2号内核线程始终运行在内核空间,是所有内核态其它守护线程的父线程。

3.总结

计算机3大法宝:存储程序计算机,函数调用堆栈,中断。

操作系统2把宝剑:中断上下文的切换(保存现场和中断现场),进程上下文的切换。

内核源代码根目录下的几个关键目录:

  • block:存放linux存储体系中关于块设备管理的代码
  • crypto:存放常见的加密算法的C语言代码
  • Documentation: 存放一些文档
  • drivers:驱动目录,里面分门别类的存放了linux内核支持的所有硬件设备的驱动源代码
  • firmware:固件
  • fs:文件系统,里面列出了linux支持的各种文件系统的实现
  • include:头文件目录,存放公共的头文件
  • init:存放linux内核启动时的初始化代码
  • kernel:存放内核本身需要的一些核心代码文件
  • lib:公用的库文件,里面是一些公用的库函数
  • mm:存放linux的内存管理代码
  • net:存放与网络相关的代码,例如TCP/IP协议栈等
posted @ 2020-11-01 13:44  20209321  阅读(121)  评论(0编辑  收藏  举报