zoukankan      html  css  js  c++  java
  • 2018-2019-1 20189203《Linux内核原理与分析》第四周作业

    第一部分 课本学习

    • 内核版本号:Linux内核自2013年12月起,就以A.B.C.D的方式命名。A和B变得无关紧要,C是内核的真实版本。每一个版本的变化都会带来新的特性,如内部API的变化等,改动的代码数量常常上万行。D是安全补丁和bug修复。
    • 几个关键的目录:
      Arch:与体系结构相关的子目录列表。
      Block:存放Linux存储体系中关于块设备管理的代码。
      Crypto:存放常见的加密算法的C语言代码。
      Documentation:存放一些文档。
      Drivers:驱动目录,里面分门别类地存放了Linux内核支持的所有硬件设备的驱动源代码。
      Firmware:固件。
      Fs:文件系统,里面列出了Linux支持的各种文件系统的实现。
      Include:头文件目录,存放公共的头文件。
      Init:init是初始化的意思,存放Linux内核启动时的初始化代码。
      Ipc:里面是Linux支持的IPC的代码实现。
      Kernel:存放内核本身需要的一些核心代码文件。其中有很多关键代码,包括pid--进程号等。
      Lib:公用的库文件,里面是一些公用的库函数。
      Mm:存放LInux的内存管理代码。
      Net:该目录下是网络相关的代码,譬如TCP/IP协议栈等。
    • 编译配置Linux内核的关键步骤:
      1、编译安装步骤
      安装开发组包>下载源码文件>.config: 准备配置文件>make menuconfig: 配置内核选项>make[-j#]>make modules_install: 安装模块>make install:安装内核相关文件>安装bzImage 为 /boot/vmlinuz-VERSION-RELEASE>生成initramfs>编辑grub的配置文件。
      2、编译配置选项
      (1)配置内核选项
      (2)支持“更新”模式进行配置:make help
      Make config:基于命令行以遍历的方式去配置内核中可配置的每个选项。
      Make menuconfig:基于命令行以遍历的方式去配置内核中可配置的每个选项。
      Make gconfig:基于GTK(GNOME)环境窗口界面。
      Make xconfig: 基于QT(KDE)环境的窗口界面。
      (3)支持“全新配置”模式进行配置
      Make defconfig:基于内核为目标平台提供的“默认”配置进行配置。
      Make allyesconfig:所有选项均回答为“yes”。
      Make allnoconfig:所有选项均回答为“no”。
      3.编译
      全编译:make[-j#]

    第二部分 实验操作

    • 在实验楼环境下输入:
    cd LinuxKernel/
    qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
    

    完成启动内核的操作,如下图:

    • 几个指令的含义:
      qemu :相当于打开一个虚拟机
      kernel:启动一个内核,位置由其后的文件名指定。
      bzImage是vmLinux经过gzip压缩后的文件,是压缩的内核映像。vmLinux是编译出来的最原始的内核ELF文件。
      initrd是“initial ramdisk”的简写,普通linux用户一般感受不到这个内存根文件系统的存在,内核启动先访问initrd文件系统,然后在切换到磁盘文件系统。
    • 使用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之前,也可以在之后
    
    • 操作如下:
      加载符号表:

      链接gdbserver:

      设置一个断点

      查看start_kernel函数的上下文

    第三部分 分析从start_kernel到init进程启动的过程

    1、start_kernel()

    代码如下:

    • main.c中没有main函数,start_kernel()相当于C语言中的main函数。Start_kernel是一切的起点,在此函数被调用之前,内核代码主要是用汇编语言写的,用于完成硬件系统的初始化工作,为C代码的运行设置环境。

    2、init_task()

    代码如下:

    • init_task(0号进程)是task_struct类型,是进程描述符,使用宏INIT_TASK对其进行初始化。接下来就是对各模块的初始化。

    3.rest_init()

    代码如下:

    • rest_init()这个函数调用系统函数 kernel_thread() 创建 1 号进程,即 init 进程,是用户态所有进程的祖先。然后,新建 kthreadd 进程,是内核态所有进程的祖先。最后,通过 cpu_startup_entry 函数启动 0 号进程。
      Init_task()(PID为0)在创建了init进程后,调用cpu_idle()演变成idle进程,执行一次调度后,init进程运行。1号内核线程负责执行内核的部分初始化工作及进行系统配置,最后调用do_execve加载init程序,演变成init进程(用户态1号进程),init进程是内核启动的第一个用户态进程。Kthreadd(PID为2)进程由0号进程创建,始终运行在内核空间,负责所有内核线程的调度和管理。
  • 相关阅读:
    计算一个月有多少天
    模拟迭代器next方法
    Promise实现
    控制台命令
    Linux下通过ssh上传下载文件
    简单使用template-web.js
    安装echo框架
    gin框架博客实战教程2019web页面开发go语言实战博客开发
    TP5使用phpoffice phpexcel包操作excel(导出)
    两分钟让你明白Go中如何继承
  • 原文地址:https://www.cnblogs.com/23du/p/9892204.html
Copyright © 2011-2022 走看看