zoukankan      html  css  js  c++  java
  • Linux内核分析——构造一个简单的Linux系统MenuOS

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

    一、Linux内核源代码简介

    1、计算机三大法宝

      存储程序计算机

      函数调用堆栈

      中断机制

    2、操作系统两把宝剑

      中断上下文的切换

      进程上下文的切换

    3、函数目录

      Linux-3.18.6/arch/x86

      内核启动相关的代码基本都存在init目录中。

      start_kernel函数相当于普通C程序的main函数。

      Linux内核的核心代码在kernel目录中。

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

    实验过程:

    进入实验楼的虚拟机,打开shell。

    cd Linuxkernel/

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

     

    内核启动完成后进入menu程序,支持命令help、version和quit。

    三、使用gdb跟踪调试Linux内核的方法

    1、使用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)

      # -s shorthand for -gdb tcp::1234 若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项

     

    当前状态是被冻结起来的。

    2、gdb设断点

    (1)另外打开一个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之前,也可以在之后

    (2)设置完断点后,输入c命令继续执行,函数会停在断点处。

     

    (3)输入list指令可以查看断点处的代码。

    四、简单分析start_kernel

    1、全局变量init_tast:即手工创建的pcb,0号进程即最终的idle进程。

    2、trap_init:硬件中断,初始化一些中断向量,系统调用。

       set_intr_gate:设置中断门。

         set_system_trap_gate:系统陷阱门SYSCALL VECTOR。

    3、mm_init:内存管理模块初始化。

    4、sched_init:进程调度初始化函数,函数内做了很关键的一步初始化——对0号进程,即idle进程进行初始化。

    5、rest_init:其他初始化函数,函数内将创建1号进程,即init进程。

    6、init_process:是linux系统中的1号进程,是第一个用户态进程,默认根目录下的init程序。

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

    五、总结

      1、道生一,一生二,二生三,三生万物。

      2、start_kernel函数相当于普通C程序的main函数。内核启动过程包括start_kernel之前和之后,之前全部是做初始化的汇编指令,之后开始C代码的操作系统初始化,最后执行第一个用户态进程init。

      3、总的来说,x86架构的Linux内核启动过程分为6大步,分别为:
         (1)实模式的入口函数_start():在header.S中,这里会进入众所周知的main函数,它拷贝bootloader的各个参数,执行基本硬件设置,解析命令行参数。
         (2)保护模式的入口函数startup_32():在compressed/header_32.S中,这里会解压bzImage内核映像,加载vmlinux内核文件。
         (3)内核入口函数startup_32():在kernel/header_32.S中,这就是所谓的进程0,它会进入体系结构无关的start_kernel()函数,即众所周知的Linux内核启动函数。start_kernel()会做大量的内核初始化操作,解析内核启动的命令行参数,并启动一个内核线程来完成内核模块初始化的过程,然后进入空闲循环。
         (4)内核模块初始化的入口函数kernel_init():在init/main.c中,这里会启动内核模块、创建基于内存的rootfs、加载initramfs文件或cpio-initrd,并启动一个内核线程来运行其中的/init脚本,完成真正根文件系统的挂载。
         (5)根文件系统挂载脚本/init:这里会挂载根文件系统、运行/sbin/init,从而启动众所周知的进程1。
           (6)init进程的系统初始化过程:执行相关脚本,以完成系统初始化,如设置键盘、字体,装载模块,设置网络等,最后运行登录程序,出现登录界面。

  • 相关阅读:
    android 工具类 DateUtil
    POJ1580 水题,积累!
    POJ1159,Palindrome
    iOS开发UI篇章 15-项目中的常见文件
    MongoDB:Map-Reduce
    三层架构下实现用户登陆C#
    Inno Setup 安装inf文件的一个例子
    delphi 主线程向子线程发送消息
    PeekMessage和GetMessage函数的主要区别
    delphi SPCOMM的一些用法注意
  • 原文地址:https://www.cnblogs.com/20135235my/p/5268446.html
Copyright © 2011-2022 走看看