磨刀不误砍柴工——实验工具准备
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依赖于zlib,glib,sdl,同时glib依赖libffi。所以为了成功编译qemu,需要提前编译安装如上4个包,编译方法就是linux的源码安装3步曲——configure,make,make 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.html:3.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为添加给内核的参数。
二)交叉编译工具
为什么需要交叉编译工具呢?目前我们有最多的参考资料,最成熟的技术,是建立在x86的32位系统中的,但是目前我们电脑已经到了64位,所以我们需要在64位系统中编译出32位运行系统,这样尽可能方便调试系统。而对于64位系统或者其他处理器——比如:ARM,可以看作是系统的扩展与移植,当我们熟悉x86的32位系统中,就可以将某些概念与技术进行推广,然后通过差异化去理解相关的概念。
网上有很多交叉编译工具的编译方法,都是我们的参考,但是能不能成功,这就需要自己动手实验了。
如下所描述的内容都是参考,只有自己动手去尝试才能保证其正确性,因为每个人的实验环境不一样。
所以如下为老生常谈的内容,同时交叉编译工具的制作是很麻烦的,而且需要很多配置的信息,大都需要详细参考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,isl,kernel头文件
-->binutils
因为编译器gcc依赖glibc与binutils,而glibc又依赖于glibc-ports,mpfr,mpc,gmp,isl,kernel头文件。
所以需要到各自的官网上下载最新的源代码即可,然后放到目录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内核?一个很直接的原因就是梳理内核的启动流程与调试内核的关键流程,能够对内核进行动态分析,不仅仅停留在静态分析上,更深入去理解内核。推荐一个查看内核源代码的工具——LXR:http://lxr.oss.org.cn/ident。
我们以如下步骤进行调试:以上是关于磨刀不误砍柴工——实验工具准备的主要内容,如果未能解决你的问题,请参考以下文章