20135220谈愈敏Blog3_构造一个简单的Linux系统MenuOS

构造一个简单的Linux系统MenuOS

谈愈敏 原创作品转载请注明出处 《Linux内核分析》MOOC课程 http://mooc.study.163.com/course/USTC-1000029000

Linux内核源代码

回顾:

计算机三大法宝

  • 存储程序计算机
  • 函数调用堆栈
  • 中断

操作系统两把宝剑

  • 中断上下文的切换
  • 进程上下文的切换

Linux内核源代码简介

  • arch/x86目录下的代码是重点关注的
  • init目录:内核启动相关的代码基本都在init目录下
  • init/main.c中start_kernel函数就相当于普通C程序的main函数
  • fs目录:file system文件系统
  • ipc目录:进程间通信
  • kernel目录:Linux内核核心代码在kernel目录中

构造一个简单的Linux系统

实验过程

使用实验楼的虚拟机打开shell

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

qemu:启动一个虚拟机平台

-kernel:给一个内核,操作系统

-initrd:驱动所需的硬盘

rootfs.img:放一个可执行文件由menuOS源代码编译成的init

内核启动完成:

输入help,可以发现系统支持三个命令help、version和quit:

使用gdb跟踪调试内核

qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S 
关于-s和-S选项的说明:
# -S freeze CPU at startup (use ’c’ to start execution)指在CPU初始化之前(刚启动的时候)将其冻结
# -s shorthand for -gdb tcp::1234 指在1234这个端口上创建的gdb server,若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

另开一个shell窗口(使用水平分割)

gdb
(gdb)file linux-3.18.6/vmlinux # 在gdb界面中targe remote之前加载符号表
(gdb)target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
(gdb)break start_kernel # 断点的设置可以在target remote之前,也可以在之后

符号:全局函数名,全局变量名,汇编时没有,不需要符号只是一个地址,但调试时需要,所以有符号表:符号与在内存中地址的一一对应。

设置完断点之后,输入c命令continue继续执行,函数会停在断点处
输入list指令之后,可以详细地查看断点附近的代码:

总结分析start_kernel

start_kernel:包括很多模块的初始化。

不管分析内核的哪一部分都会涉及到start_kernel,都会在init初始化。

1、全局变量init_task

其中有一个全局变量init_task,即手工创建的PCB,0号进程即最终的idle进程。

2、trap_init

trap_init涉及到中断,初始化一些中断向量

set_intr_gate:设置中断门
set_system_trap_gate:系统陷阱门SYSCALL VECTOR

分析中断时主要分析系统调用,系统调用是用指令的方式触发中断。硬件中断不好模拟分析。

3、mm_init

mm_init:内存管理模块初始化

4、sched_init

sched_init:调用进程调度初始化

5、rest_init

rest_init中:

kernel_init:创建1号进程
第一个用户态进程:init_process,1号进程,找默认路径下的程序作为1号进程

kthreadd:内核线程,用来管理系统资源

当系统没有进程需要执行时就调度idle进程,即0号进程,一直存在。

总结内核启动过程

道生一(start_kernel....cpu_idle)
一生二(kernel_init和kthreadd)
二生三(即前面0、1和2三个进程)
三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)
新内核的核心代码已经优化的相当干净,都符合中国传统文化精神了。

Linux内核启动过程相关的参考资料

计算机的启动过程概述

  • x86 CPU启动的第一个动作CS:EIP=FFFF:0000H(换算为物理地址为000FFFF0H,因为16位CPU有20根地址线),即BIOS程序的位置。http://wenku.baidu.com/view/4e5c49eb172ded630b1cb699.html
  • BIOS例行程序检测完硬件并完成相应的初始化之后就会寻找可引导介质,找到后把引导程序加载到指定内存区域后,就把控制权交给了引导程序。这里一般是把硬盘的第一个扇区MBR和活动分区的引导程序加载到内存(即加载BootLoader),加载完整后把控制权交给BootLoader。
  • 引导程序BootLoader开始负责操作系统初始化,然后起动操作系统。启动操作系统时一般会指定kernel、initrd和root所在的分区和目录,比如root (hd0,0),kernel (hd0,0)/bzImage root=/dev/ram init=/bin/ash,initrd (hd0,0)/myinitrd4M.img
  • 内核启动过程包括start_kernel之前和之后,之前全部是做初始化的汇编指令,之后开始C代码的操作系统初始化,最后执行第一个用户态进程init。
  • 一般分两阶段启动,先是利用initrd的内存文件系统,然后切换到硬盘文件系统继续启动。initrd文件的功能主要有两个:1、提供开机必需的但kernel文件(即vmlinuz)没有提供的驱动模块(modules) 2、负责加载硬盘上的根文件系统并执行其中的/sbin/init程序进而将开机过程持续下去
posted on 2016-03-10 12:04  20135220谈愈敏  阅读(251)  评论(1编辑  收藏  举报