zoukankan      html  css  js  c++  java
  • 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程序进而将开机过程持续下去
  • 相关阅读:
    【Redis】跳跃表原理分析与基本代码实现(java)
    小鹤音形指引
    Maven
    算法思维(长期更)
    多路平衡树之红黑树
    多路平衡树之B树
    多路平衡树之2-3查找树
    栈与队列
    树基本概念
    Vue学习
  • 原文地址:https://www.cnblogs.com/tymjava/p/5261356.html
Copyright © 2011-2022 走看看