第三周:构造一个简单的LINUX系统MENUOS

吕松鸿 + 原创做品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
linux

1、Linux内核源码简介

1.操做系统的两把宝剑shell

  •   中断上下文的切换——保存现场&恢复现场
  •   进程上下文的切换

2.Linux内核源代码简介tcp

(1)打开内核源代码页面函数

  •   arch/目录:支持不一样CPU的源代码;其中的X86是重点
  •   init/目录:内核启动相关的代码基本都在该目录中
  •   start_kernel函数就至关于普通C程序的main函数
  • kernel/目录:Linux内核核心代码在kernel目录中

(2)READMEoop

提供内核的各类编译方法、生成文件的查看方法。例如:ui

  •   INSTALLING 如何安装内核源代码
  •   make mrproper 清理安装时生成的中间代码

2、构造一个简单的Linux系统

1. 运行MenuOS系统spa

在实验楼的虚拟机环境里,打击打开shell,使用下面的命令操作系统

cd LinuxKernel/

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

# -initrd:指明一个根文件系统

  • 启动实验的Linux系统MenuOS,实际上就是一个在Linux内核的基础上,再运行一个简单菜单命令行程序。
  • 在MenuOS>的提示符下输入help,看到其所有支持的命令:命令行

    help、version、quit

2. 使用gdb跟踪调试内核

  • 使用带参数命令启动MenuOS,使得系统在刚启动时,暂停等待调试器跟踪执行。线程

    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
    # -S 在CPU初始化以前,冻结CPU
    # -s 1234端口上建立一个tcp接口。若不想使用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 
    # 在start_kernel函数入口处设置断点
    (gdb)c 
    # 使得系统运行到start_kernel处停住
    (gdb)list
    # 显示当前行所在位置上下的代码

 

3、简单分析start_kernel

(1)全局变量 init_task

全局变量init_task,即手工建立的PCB,0号进程初始化,0号进程就是最终的idle。

500asmlinkage __visible void __init start_kernel(void)
501{
502 char *command_line;
503 char *after_dashes;
504
505 /*
506  * Need to run as early as possible, to initialize the
507  * lockdep hash:
508  */
509 lockdep_init();
510 set_task_stack_end_magic(&init_task);//init_task即手工建立的PCB,0号进程及最终的idle进程
511 smp_setup_processor_id();
512 debug_objects_early_init();

(2)初始化一些中断向量 trap_init()

中断向量表的初始化函数,设置了不少中断门(Interrupt Gate)

set_intr_gate:设置中断门

(3)内存管理模块初始化 mm_init()

(4)调度模块初始化 sched_init()

函数内作了很关键的一步初始化——对0号进程,即idle进程进行初始化。

(5)其它模块初始化 rest_init()

kernel_thread(kernel_init,NULL,CLONE_FS)中的kernel_init包含一个run_init_process,建立了一号进程,即第一个用户态进程。以后建立了kthreadd,一个内核线程来管理系统的资源。

 

  •   建立了一号进程后,kernel_thread函数经过405行的kthreadd管理线程;
  •   由cpustartupentry(CPUHPONLINE);——>cpuidleloop();——>static void cpuidle_loop(void):
  •   cpuidleloop中有一个while循环,当start_kernel启动以后,她就一直存在。当系统没有进场须要执行的时候就调度到idle进程

4、总结

1.kernelthread是0号进程,它建立了1号进程kernelinit,以及它的一些服务的内核线程,这样整个系统及启动起来了;

2.而后init进程会再启动一些进程。

相关文章
相关标签/搜索