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程序进而将开机过程持续下去
  • 相关阅读:
    布局重用 include merge ViewStub
    AS 常用插件 MD
    AS 2.0新功能 Instant Run
    AS .ignore插件 忽略文件
    AS Gradle构建工具与Android plugin插件【大全】
    如何开通www国际域名个人网站
    倒计时实现方案总结 Timer Handler
    AS 进行单元测试
    RxJava 设计理念 观察者模式 Observable lambdas MD
    retrofit okhttp RxJava bk Gson Lambda 综合示例【配置】
  • 原文地址:https://www.cnblogs.com/tymjava/p/5261356.html
Copyright © 2011-2022 走看看