• LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS


    LINUX内核分析第三周学习总结——构造一个简单的Linux系统MenuOS

    标签(空格分隔): 20135321余佳源


    余佳源(原创作品转载请注明出处)

    《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000


    一、知识点总结

    计算机三个法宝

    存储程序计算机
    函数调用堆栈
    中断

    操作系统两把宝剑

    中断上下文的切换
    进程上下文的切换

    Linux内核源代码简介分析

    链接戳这--->Linux内核源代码

    概要分析:
    ·arch/目录保存支持多种CPU类型的源代码,包括:Documentation、drivers、firewall、fs(文件系统)、include
    ·init目录:含有main.c,内核启动相关的代码基本都在init目录下
    ·start_kernal()函数为启动函数,初始化内核的起点。
    ·ipc目录:进程间的通信
    ·kernel目录:有Linux内核的核心代码。
    ·pid.c、kthread.c

    lib目录:公用库文件 
    mm目录:内存管理代码 
    net目录:与网络相关代码 
    scripts目录:与脚本相关 
    security目录:与安全相关 
    sound目录:与声音相关 
    tools目录:与工具相关
    
    README文件:
    介绍了什么是Linux,Linux能够在哪些硬件上运行,如何安装内核源代码等
    

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

    实验环境:
    VMware 虚拟机 Linux 系统 Ubuntu kylin 14.02

    准备:下载好Linux-3.18.6.tar,通过xz -d linux-3.18.6.tar.xz 以及 tar -xvf linux-3.18.6.tar命令解开压缩。

    实验步骤:

    1.cd linux-3.18.6进入到具体操作的文件夹

    2.make i386_defconfig进行编译

    3.使用make menuconfig进行内核配置,在图中项打上*,具体选项如下

    kernel hacking—>
    [*] compile the kernel with debug info

    4.制作根文件系统
    在LinuxKernel目录下创建文件夹rootfs,通过git clone https://github.com/mengning/menu.git下载menu压缩包,解压缩后进入

    5.在menu文件夹里进行可执行文件的编译
    gcc -o init linktable.c menu.c test.c -m32 -static –lpthread

    6.提取出根文件系统rootfs.img
    cp ../menu/init ./ find . | cpio -o -Hnewc |gzip -9 > ../rootfs.img

    7.启动根文件系统并准备使用GDB调试,由于是本地的虚拟机,所以和指导书上的路径有不同,而且启动指令改为

    qemu-system-x86_64 -kernel  /home/brotherlittlefish/LinuxKernel/linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img -s -S
    -S freeze CPU at startup (use ’c’ to start execution)//在启动的时候冻结CPU,可在GDB调试中按'c'执行
    -s shorthand for -gdb tcp::1234 //设定一个端口,若不想使用1234端口,则可以使用-gdb tcp:xxxx来取代-s选项
    

    此时这个Ubuntu虚拟机中的虚拟机qemu处于冻结状态

    8.使用另一个终端启动gdb,打开可执行文件vmlinux,在gdb界面中targe remote之前加载符号表

    一句话:从vmlinux中读取符号表,完成

    9.进行GDB调试

    输入
    ——> target remote:1234 # 建立gdb和gdbserver之间的连接,按c 让qemu上的Linux继续运行
    ——>break start_kernel # 断点的设置可以在target remote之前,也可以在之后
    ——>按下c启动程序解除冻结

    ——>按下list,可以看见start_kernel的具体情况

    ——>break rest_init # 断点设置在rest_init这个函数,如同start_kernel的步骤

    10.不设置断点,让根文件系统MENUOS继续运行直到完成开机

    PS:输入help可见到该MENUOS有什么具体的功能指令

    三、建立系统过程的总结分析

    1.关于start_kernel

    在init目录下main.c里找到start_kernel函数

    可见有一个全局变量init_task,即手工创建的PCB,0号进程即最终的idle进程。0号进程创建了1号进程和其他线程,也就是说不管分析内核的哪一部分都会涉及到start_kernel。

    2.三个相关的init

    trap_init();初始化一些中断向量
    mm_init() 内存管理模块
    sched_init() 调度模块

    其中rest_init()中有kernel_thread(kernel_init,NULL,CLONE_FS),它是0号进程,创建了1号进程kernel_init()
    

    而kernel_thread()中有kernel_init(),kernel_init()包含了run_init_process,

    kernel_init 是linux系统的1号进程,第一个用户态进程,默认根目录下的init程序。
    kernel_thread()还创建了kthreadd,一个内核线程来管理系统的资源。

    启动完了之后进入了一个cpu_idle,cpu_idle_loop,就是一个while(0)的无限循环,即idle进程,0号进程,一直存在
    当系统没有进程需要执行时就调度到idle进程。

    3.小结

    rest_init就是start_kernel内核启动时一直存在,即为0号进程。0号进程创建了1号进程kernel_init以及其他的服务线程。“道生一(start_kernel....cpu_idle)、一生二(kernel_init和kthreadd)、二生三(即前面0、1和2三个进程)、三生万物(1号进程是所有用户态进程的祖先,2号进程是所有内核线程的祖先)”,内核就启动了。
    
  • 相关阅读:
    类和迭代器
    使用委托调用函数
    自定义类和集合
    带函数的参数返回函数的最大值
    使用程序调试输出窗口
    自定义类
    类和结构
    全局参数
    带参数的函数返回数组之和
    IS运算符
  • 原文地址:https://www.cnblogs.com/brotherlittlefish/p/5269864.html
Copyright © 2020-2023  润新知