zoukankan      html  css  js  c++  java
  • Linux内核分析——第三周学习笔记20135308

    第三周 构造一个简单的Linux系统MenuOS

    计算机三个法宝:

    1、存储程序计算机

    2、函数调用堆栈

    3、中断

    操作系统两把宝剑:

    1、中断上下文的切换:保存现场和恢复现场

    2、进程上下文的切换

    一、阅读Linux内核代码

    本周我们要学习如何阅读Linux内核源代码,首先打开Lstest Stable Kernel:linux-3.18.6

    arch/目录在Linux内核中占有相当庞大的代码量,因为Linux支持很多CPU,这个arch/x86目录下的代码是我们重要关注的代码

    根目录中比较关键的目录:

    • Documentation/文档
    • fs/文件系统
    • init/内核启动相关的代码基本都在init目录下,里面的main.c是整个Linux内核启动的起点。它的起点是start_kernel

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

    如上图所示,第500行这里就是初始化Linux内核的起点,之前的部分是汇编做硬件初始化。

    • ipc/进程间通信
    • kernel/Linux内核的核心代码在kernel目录中
    • lib/公用的库文件
    • mm/memmory management内存管理
    • net/与网络相关的代码
    • security/与安全相关的代码
    • scripts/脚本

    以上加粗的部分为我们重点关注的。

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

     

    方法一:使用实验楼的虚拟机打开shell

    linux-3.18.6.tar就是内核源代码,rootfs里面有用menu编译好的init可执行文件,rootfs.img是它生成的。

    该系统支持三条命令:help、version和quit

    输入help会有以下三条命令

    使用gdb跟踪调试内核

    输入以下命令

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

    -S表示:在CPU初始化之前,冻结CPU

    -s表示在:1234端口上创建一个tcp接口

    如图所示,是被冻结状态的。

    水平分割,再打开一个shell窗口,输入gdb

    这里注意:视频中孟老师是直接进入了LinuxKernel文件夹,我们要在实验楼中进入LinuxKernel再gdb,否则会显示找不到文件。

    输入(gdb)file linux-3.18.6/vmlinux

    targe remote之前加载符号表

    Reading后,连接到刚启动的被冻结的linux系统,设置断点,把内核启动的起点start_kernel设为断点,在init/main.c文件中,第501行

    输入c,回车,系统从冻结状态开始执行,启动。

    输入list,可以看见start_kernel代码上下的这段代码

    再设一个断点rest_init,按c继续执行

    系统已经执行到rest_init

    输入list,看rest_init前后的代码

    在start_kernel尾部被调用

    方法二:使用自己的Linux系统环境搭建MenuOS

    首先,下载内核源代码编译内核,大概几百M

    接下来,make,大概会make20多分钟

    下面,制作根文件系统,我首先尝试了孟老师的第一种方法,在GitHub上注册账号,登录,然而显示Error 403

    之后,我用第二种办法,在课程的“课件”页面,底部单击“下载附件”



    下载menu.zip,并共享到虚拟机中去

    继而,gcc编译

    在rootfs文件夹出现了编译出的镜像文件

    由于自己的虚拟机缺少配置,不能进行下去了

    三、简单分析一下start_kernel

    首先设置全局变量init task,相当于手工创建的PCB,0号进程就是最终的idle进程,0号进程创建了1号进程和其他线程

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

    mm_init() 内存管理模块

    sched_init() 调度模块

    其中,在x86中,设置了很多中断门

    还设计系统陷阱门,系统调用的,也是一种中断

    rest_init

    kernel_init里面的run_init_process就是linux系统的1号进程,第一个用户态进程,默认根目录下的init程序

    kernel_init不仅创建了1号进程,还创建了kthreadd内核线程,来管理系统资源

    系统进入了内核启动rest_init,call into cpu_idle

    这里的cpu_idle_loop就是进入了while(0)的无限循环,就是idle0号进程。它一直存在在系统中,当没有进程需要执行时,就调度到idle进程。

    总结:rest_init就是start_kernel内核启动时一直存在,即为0号进程。0号进程创建了1号进程kernel_init以及其他的服务线程。“道生一(start_kernel....cpu_idle)、一生二(kernel_init和kthreadd)、二生三(即前面0、1和2三个进程)、三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)”,内核就启动了。

  • 相关阅读:
    K-Multiple Free set UVA-11246 (容斥原理)
    RAID! UVA-509 (奇偶校验)
    龙芯 fedora28 安装指南
    Kdenlive简明教程-简单的操作
    Kdenlive简明教程-开始
    Irrelevant Elements UVA-1635 (二项式定理)
    指针的指针笔记
    scanf 函数笔记
    printf 函数笔记
    龙芯 3A4000 Fedora28 安装笔记
  • 原文地址:https://www.cnblogs.com/bonjourvivi/p/5251169.html
Copyright © 2011-2022 走看看