LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS

LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS

标签(空格分隔): 20135321余佳源


余佳源(原创作品转载请注明出处)

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


一、知识点总结

计算机三个法宝

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

操作系统两把宝剑

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

Linux内核源代码简介分析

链接戳这--->Linux内核源代码

概要分析:
·arch/目录保存支持多种CPU类型的源代码,包括:Documentation、drivers、firewall、fs(文件系统)、include
·init目录:含有main.c,内核启动相关的代码基本都在init目录下
·start_kernal()函数为启动函数,初始化内核的起点。
·ipc目录:进程间的通信
·kernel目录:有Linux内核的核心代码。
·pid.c、kthread.c

lib目录:公用库文件 
mm目录:内存管理代码 
net目录:与网络相关代码 
scripts目录:与脚本相关 
security目录:与安全相关 
sound目录:与声音相关 
tools目录:与工具相关

README文件:
介绍了什么是Linux,Linux能够在哪些硬件上运行,如何安装内核源代码等

二、构造一个简单的Linux系统MenuOS

实验环境:
VMware 虚拟机 Linux 系统 Ubuntu kylin 14.02

准备:下载好Linux-3.18.6.tar,通过xz -d linux-3.18.6.tar.xz 以及 tar -xvf linux-3.18.6.tar命令解开压缩。

实验步骤:

1.cd linux-3.18.6进入到具体操作的文件夹

2.make i386_defconfig进行编译

3.使用make menuconfig进行内核配置,在图中项打上*,具体选项如下

kernel hacking—>
[*] compile the kernel with debug info

4.制作根文件系统
在LinuxKernel目录下创建文件夹rootfs,通过git clone https://github.com/mengning/menu.git下载menu压缩包,解压缩后进入

5.在menu文件夹里进行可执行文件的编译
gcc -o init linktable.c menu.c test.c -m32 -static –lpthread

6.提取出根文件系统rootfs.img
cp ../menu/init ./ find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

7.启动根文件系统并准备使用GDB调试,由于是本地的虚拟机,所以和指导书上的路径有不同,而且启动指令改为

qemu-system-x86_64 -kernel  /home/brotherlittlefish/LinuxKernel/linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
-S freeze CPU at startup (use ’c’ to start execution)//在启动的时候冻结CPU,可在GDB调试中按'c'执行
-s shorthand for -gdb tcp::1234 //设定一个端口,若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

此时这个Ubuntu虚拟机中的虚拟机qemu处于冻结状态

8.使用另一个终端启动gdb,打开可执行文件vmlinux,在gdb界面中targe remote之前加载符号表

一句话:从vmlinux中读取符号表,完成

9.进行GDB调试

输入
——> target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
——>break start_kernel # 断点的设置可以在target remote之前,也可以在之后
——>按下c启动程序解除冻结

——>按下list,可以看见start_kernel的具体情况

——>break rest_init # 断点设置在rest_init这个函数,如同start_kernel的步骤

10.不设置断点,让根文件系统MENUOS继续运行直到完成开机

PS:输入help可见到该MENUOS有什么具体的功能指令

三、建立系统过程的总结分析

1.关于start_kernel

在init目录下main.c里找到start_kernel函数

可见有一个全局变量init_task,即手工创建的PCB,0号进程即最终的idle进程。0号进程创建了1号进程和其他线程,也就是说不管分析内核的哪一部分都会涉及到start_kernel。

2.三个相关的init

trap_init();初始化一些中断向量
mm_init() 内存管理模块
sched_init() 调度模块

其中rest_init()中有kernel_thread(kernel_init,NULL,CLONE_FS),它是0号进程,创建了1号进程kernel_init()

而kernel_thread()中有kernel_init(),kernel_init()包含了run_init_process,

kernel_init 是linux系统的1号进程,第一个用户态进程,默认根目录下的init程序。
kernel_thread()还创建了kthreadd,一个内核线程来管理系统的资源。

启动完了之后进入了一个cpu_idle,cpu_idle_loop,就是一个while(0)的无限循环,即idle进程,0号进程,一直存在
当系统没有进程需要执行时就调度到idle进程。

3.小结

rest_init就是start_kernel内核启动时一直存在,即为0号进程。0号进程创建了1号进程kernel_init以及其他的服务线程。“道生一(start_kernel....cpu_idle)、一生二(kernel_init和kthreadd)、二生三(即前面0、1和2三个进程)、三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)”,内核就启动了。
posted @ 2016-03-12 19:54  20135321余佳源  阅读(289)  评论(2编辑  收藏  举报