构造一个简单的Linux系统MenuOS

来源:互联网 发布:php 微信网页授权代码 编辑:程序博客网 时间:2024/06/05 15:17

林万喜 原创作品 转载请注明出处  USTC  2015.3

《Linux内核分析》MOOC课程:在线课程链接http://mooc.study.163.com/course/USTC-1000029000 

微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑微笑



一、操作过程
  • 1.使用实验楼的虚拟机打开shell

  1. cd LinuxKernel/
  2. qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img





  • 2.使用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中进行一系列极为重要的初始化。最后执行位于init/main.c中的rest_init()来创建系统的第一个进程init。至此,内核启动完成。之后init进程会进行一些初始化和根文件系统挂载。

在start_kernel()的最后,系统会调用rest_init(),通过执行其中的kernel_thread(init, NULL, CLONE_FS | CLONE_SIGHAND)来创建系统的第一个进程,即init进程。Init进程首先进行一系列的硬件初始化,然后挂载根文件系统。最后 init 进程会执行用户传递过来的“init=”启动参数执行用户指定的命令,或者执行以下几个进程之一:
execve(“/sbin/init”,argv_init,envp_init);
execve(“/etc/init”,argv_init,envp_init);
execve(“/bin/init”,argv_init,envp_init);
execve(“/bin/sh”,argv_init,envp_init)。

如果这些都无法执行(无法找到),系统的启动会宣告失败。Init启动后,会读取/etc/inittab这一配置文件,根据inittab文件内容进行一些设置或对一些指令做出解释。


三、总结
 idle是一个进程,其pid号为 0。其前身是系统创建的第一个进程,也是唯一一个没有通过fork()产生的进程。每个处理器单元有独立的一个运行队列,而每个运行队列上又有一个idle进程,即有多少处理器单元,就有多少idle进程。
        加载linux内核开始运行后,进程开始执行start_kernel()完成Linux内核的初始化工作。包括初始化页表,初始化中断向量表,初始化系统时间等。继而调用 fork(),创建第一个用户进程:  kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); 这个进程就是着名的pid为1的init进程,它会继续完成剩下的初始化工作,然后execve(/sbin/init), 成为系统中的其他所有进程的祖先。这就是我们看到的init进程,进程号为1。初始化的最后linux调用scheule()整个系统就运行起来了。可以用进程查看命令来验证  # ps aux  。
        



0 0
原创粉丝点击