磨刀不误砍柴工——实验工具准备

Posted yiye_01

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了磨刀不误砍柴工——实验工具准备相关的知识,希望对你有一定的参考价值。

        写在最前面的话:

   后面的一系列博客主要围绕MIT-OS的学习课程来创建;

   为什么会学习mit-os?
   1)对于复杂的事物,一种常见的思维就是从简单到复杂的思维。根据这种思维去学习原始的os,透过它去熟悉os的基本概念与核心构造,从而以此作为基础去学习现代os的各项技术,能够去更新创造与优化它们。
   2)一种典型的西方逻辑思维——原子思想,所有系统都是可以分解为原子结构,然后有序的组合;根据这种思维,很容易将os分割成若干流程或者若干结构的有序组合;而且在学习过程中,发现这种课程是很好的学习模板,它通过代码的方式去引导学习去实现相关的流程与结构,这样更有利于掌握与学习学习内容。
   3)从一个更完整的角度去学习os,因为os是最贴近硬件,所以需要接触硬件的相关知识,特别是处理器的软件参考手册,从一个狭窄的角度会发现,os是处理器的软件驱动;对于os,个人认为一定需要自己尝试去实现相关部分流程或者模块,同时去调试os,才能更与os贴近,从而得到更深刻的理解。

   具体课程可以到如下网址参考:http://pdos.csail.mit.edu/6.828/2012/schedule.html

      俗话说得好磨刀不误砍柴工,有了好刀才能势如破竹的砍柴;也只有当把工具与环境有更好,更深的认识,才能将系统的知识有效的模拟与调试,才能将书本上的知识带入到实际工程中来;以工程的态度去对待所学到的知识,将理论与实践相结合,从而对概念有更深入的理解。

     从某种角度来说,对于代码或者软件来说,更多的是经验的累计与总结;而且它很实在,它可以实现自己的思想,同时也能够被直观的看到与仿真,说白了,就是任何代码或者最好是能够运行它,然后调试它,从实际运行过程中去体会它的意义,从而能够更好的理解,然后被直接使用。目前最常用的代码分析方法,就是看源代码,这样静态的去分析与理解,这种方式很直观而且有效,但是它只是停留在逻辑层面,忽略了实实在在运行环境,这样很容易只是理解思想,很难对学习者有更好的启发与提升;所以我的建议是,任何代码都请去调试它,或者自己去实现它,在模拟环境中调试之。

        对于操作系统的调试,目前有现成的解决方案就是用虚拟机去运行之,透过虚拟机平台去调试它;所以对于MIT—OS的实验课程所需要的工具与环境就是虚拟机。当然,以此作为平台,我们也可以去调试linux的内核。还有需要了解的一种工具就是链接源代码与系统的工具——编译器。所以我们会从如下2个方面去准备我们的工具与实验环境,1个实验环节来展示它们的力量。

       前面两个方面可以参考如下的部分:http://pdos.csail.mit.edu/6.828/2012/tools.html

一)虚拟机——qemu

        为什么要选择它呢?开源,而且功能强大——不仅能完全模拟pc环境,效率高,更重要的是它能与gdb调试工具直接进行交互,进行系统调试。其他更多的了解可以到官网http://wiki.qemu.org/Main_Page。当然它有很多的用处,但对于目前我们来说,更多是熟悉它的使用,能够运行我们的os,然后去调试之。

       1.下载源码:从官网http://wiki.qemu.org/Download,解压缩它。

       2.编译它,为了防止仿真的系统直接将我们的终端给控制了,所以我建议编译一个带简单窗口的版本,这样更方便我们调试系统——所以我用的是SDL的图形界面的——因为它足够简单。

      a)解决依赖关系如下:

     qemu -->zlib

              -->glib-->libffi

             -->sdl

      最新的qemu依赖于zlibglibsdl,同时glib依赖libffi。所以为了成功编译qemu,需要提前编译安装如上4个包,编译方法就是linux的源码安装3步曲——configuremakemake install

      b)配置编译参数:

 ./configure --target-list=i386-softmmu,x86_64-softmmu --enable-sdl --with-sdlabi=2.0 --enable-debug –-prefix=$YROOT

      因为我们主要模拟x86环境中的实现,所以我们只需要支持的虚拟机器构架为 --target-list=i386-softmmu,x86_64-softmmu,当然如果需要支持其他构架的实现,也可以添加其他的;支持sdl图形窗口:--enable-sdl --with-sdlabi=2.0 ;将qemu建议安装到我们的实验环境——由环境变量决定YROOT

     c)编译与安装:

     make && make install

     d)生成使用文档——html版本:qemu-doc.html

     make html

     因为生成时,有依赖关系:makeinfo-->textinfo.

     3.常用的使用命令,汇总如下:如需要更详细的参考可以用qemu-doc.html或者从官网获取http://wiki.qemu.org/Manual。如下的描述很多从qemu-doc.html摘取,而且以i386平台的工具使用,同时我们也主要使用它。

     a)基本使用方式:

      qemu-system-i386 [options] [disk_image]

      options为控制参数。

      disk_image为仿真使用的磁盘镜像,就像我们电脑使用的硬盘。

     b)处理器与内存的参数:

     -smp X :处理器核数,比如双核:-smp 2

     -m Y:内存大小,比如1G:-m 1G

     c)硬盘添加:

     -hdX(a-d) file:添加磁盘镜像文件,比如:-hdb basic.img

     d)不是用图形窗口:

      -nographic:默认qemu是会使用图形窗口,如果不是用则禁用之,它会在调试linux用到,qemu保存log到文件的功能没有用。

     e)保存debug系统信息到文件:

     -d xxx -D file:调试系统的xxx信息到文件file,比如:查看系统的反汇编——qemu-system-i386 -d in_asm -D test-d

当然可以查看系统的其他信息: qemu-system-i386 -d help

     f)添加串口:

     -serial xxx:给系统添加调试串口,这在系统调试中很重要,比如:添加当前终端为串口——-serial stdio。当然也可以查询其他的串口:qemu-system-i386 -serial [TAB][TAB]

     g)停止处理器:-S 

     h)设置gdb调试:-gdb tcp::port;使用tcp端口进行调试。这实际上就模拟了嵌入式linux系统的gdb远程调试。详细步骤可以参考《qemu-doc.html3.12 GDB usage》:当然可以参考之前我的博客关于gdb的使用。快捷gdb调试设置:-s(等价于-gdb tcp::1234)。

     i)监视器的使用:

  -monitor xxx;使用qemu监视器,通过它可以发现系统的状态,同时动态配置系统,极大的方便了系统调试。但是我们没有用。

     j)直接启动linux

qemu-system-i386 -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda"

     -kernel直接加载内核,-append为添加给内核的参数。

二)交叉编译工具

      为什么需要交叉编译工具呢?目前我们有最多的参考资料,最成熟的技术,是建立在x8632位系统中的,但是目前我们电脑已经到了64位,所以我们需要在64位系统中编译出32位运行系统,这样尽可能方便调试系统。而对于64位系统或者其他处理器——比如:ARM,可以看作是系统的扩展与移植,当我们熟悉x8632位系统中,就可以将某些概念与技术进行推广,然后通过差异化去理解相关的概念。

       网上有很多交叉编译工具的编译方法,都是我们的参考,但是能不能成功,这就需要自己动手实验了。

       如下所描述的内容都是参考,只有自己动手去尝试才能保证其正确性,因为每个人的实验环境不一样。

所以如下为老生常谈的内容,同时交叉编译工具的制作是很麻烦的,而且需要很多配置的信息,大都需要详细参考gcc官网的相关编译注释,从而我们为了简化这个流程,同时保证制作的稳定性,将相关的编译部分制作成脚本,来自动生成相关工具。在我的博客对应的资源中有脚本的实现,其中有较详细的注释,保证能够编译成功。

   参考文档:

   官方文档:https://gcc.gnu.org/install/

   编译测试结果:https://gcc.gnu.org/ml/gcc-testresults/2015-05/msg00687.html

   另外一个有效的参考文档为lfs(Linux From Scratch)相关编译步骤,其中也包含了交叉编译工具的制作——只不过它是在模拟root的方式下实现的:

从如下网址,下载最新的参考文档:http://www.linuxfromscratch.org/lfs/download.html

编译步骤如下:

    1.下载源码:

gcc-->glibc   -->glibc-ports,mpfr,mpc,gmp,islkernel头文件

      -->binutils

     因为编译器gcc依赖glibcbinutils,而glibc又依赖于glibc-ports,mpfr,mpc,gmp,islkernel头文件。

所以需要到各自的官网上下载最新的源代码即可,然后放到目录tools-src路径下。

   2.设置与创建编译,安装环境:

   ctools_instl_path=`pwd`/tools----工具安装路径

   #编译根目录

    compile_top=`pwd`/build------编译的路径

    ctarget=i486-yiye-linux------目标主机的构架,格式如下:处理器构架-制造商-运行os

    glibc_instl_path=$ctools_instl_path/$ctarget--glibc安装路径

    sysroot_path=$glibc_instl_path----系统的模拟根路径

    根据如上配置我们编译出来的交叉工具为:i486-yiye-linux-gcc,然后根据如上目录创建对应的目录。不能使用i386来标记处理器构架,因为glibc已经认为i386构架过时了,至少需要i486构架,但是不影响我们描述与使用。

     3.以如下的步骤编译所有源码:

     install_kernel_headers-------编译与安装内核头文件

     install_binutils--------编译与安装binutils工具

     install_gcc_step1------第一遍编译与安装gcc

     install_glibc---------编译与安装glibc

     install_gcc_step2-------第二遍编译与安装gcc

     如上所述,gcc被编译了两次,第一次编译是为了编译glibc,第二次编译是为了gcc能够引用我们编译出来的gcc;详细的安装步骤与解释请参考我的脚步,主要是很多细节需要去设置,当然有时可能需要去查看相关源代码,根据官方文档去猜测其真实用途。唯一一个需要多次调整gcc的使用相关库的路径。

     4.脚本的使用:

./auto_compile.sh tools-src

     然后就会生成交叉编译工具了,如下是我编译的5.1.0的 i486-yiye-linux-gcc的相关路径。

tools/

├── qemu

│   ├── glib-2.44.0

│   ├── qemu-2.3.0

│   ├── texinfo-5.2

│   └── zlib-1.2.8

├── sdl

│   └── SDL2-2.0.3

├── sources

│   ├── binutils-2.25.tar.gz

│   ├── gcc-5.1.0.tar.bz2

│   ├── glibc-2.21.tar.xz

│   ├── glibc-ports-2.16.0.tar.xz

│   ├── gmp-6.0.0a.tar.xz

│   ├── isl-0.14.tar.bz2

│   ├── linux-4.0.2.tar.xz

│   ├── mpc-1.0.3.tar.gz

│   └── mpfr-3.1.2.tar.xz

├── test

│   ├── a.out

│   ├── binutils-2.25

│   └── main.c

└── tools

    ├── bin

    ├── i486-yiye-linux

    ├── include

    ├── lib

    ├── lib64

    ├── libexec

    └── share

     编译出来的版本测试如下:

[yiye@yiye pc_prj]$ i486-yiye-linux-gcc -v

Using built-in specs.

COLLECT_GCC=i486-yiye-linux-gcc

COLLECT_LTO_WRAPPER=/home/yiye/study/pc_prj/tools/tools/libexec/gcc/i486-yiye-linux/5.1.0/lto-wrapper

Target: i486-yiye-linux

Configured with: ../gcc-5.1.0/configure --prefix=/home/yiye/study/pc_prj/tools/tools --target=i486-yiye-linux --with-sysroot=/home/yiye/study/pc_prj/tools/tools/i486-yiye-linux --with-build-sysroot=/home/yiye/study/pc_prj/tools/tools/i486-yiye-linux --with-local-prefix=/home/yiye/study/pc_prj/tools/tools/i486-yiye-linux --with-native-system-header-dir=/include --disable-nls --enable-shared --disable-static --enable-languages=c,c++ --enable-__cxa_atexit --enable-c99 --enable-long-long --enable-threads=posix --disable-multilib --with-system-zlib --enable-checking=release --enable-libstdcxx-time

Thread model: posix

gcc version 5.1.0 (GCC) 


三)单步调试linux内核

      为什么要调试linux内核?一个很直接的原因就是梳理内核的启动流程与调试内核的关键流程,能够对内核进行动态分析,不仅仅停留在静态分析上,更深入去理解内核。推荐一个查看内核源代码的工具——LXRhttp://lxr.oss.org.cn/ident

      我们以如下步骤进行调试:以上是关于磨刀不误砍柴工——实验工具准备的主要内容,如果未能解决你的问题,请参考以下文章

mac+unity3d准备工作——磨刀

欲善其事-利其器(pycharm的安装)

windows一键部署java项目

普朗克公式的计算公式

PyTorch基础——机器翻译的神经网络实现

程序员面试前必做的准备工作