📄 linux 系统内核的调试.htm
字号:
<DIV>SkyEye是一个开源软件项目(OPenSource
Software),SkyEye项目的目标是在通用的Linux和Windows平台上模拟常见的嵌入式计算机系统。SkyEye实现了一个指令级的硬件模拟平台,可以模拟多种嵌入式开发板,支持多种CPU指令集。SkyEye
的核心是 GNU 的 gdb 项目,它把gdb和 ARM
Simulator很好地结合在了一起。加入ARMulator
的功能之后,它就可以来仿真嵌入式开发板,在它上面不仅可以调试硬件驱动,还可以调试操作系统。Skyeye项目目前已经在嵌入式系统开发领域得到了很大的推广。</DIV>
<DIV><A name=IDATFAZB>3.1
SkyEye的安装和μcLinux内核编译</A></DIV>
<DIV><B>3.1.1 SkyEye的安装</B></DIV>
<DIV>SkyEye的安装不是本文要介绍的重点,目前已经有大量的资料对此进行了介绍。有关SkyEye的安装与使用的内容请查阅参考资料[11]。由于skyeye面目主要用于嵌入式系统领域,所以在skyeye上经常使用的是μcLinux系统,当然使用Linux作为skyeye上运行的系统也是可以的。由于介绍μcLinux
2.6在skyeye上编译的相关资料并不多,所以下面进行详细介绍。</DIV>
<DIV><B>3.1.2 μcLinux 2.6.x的编译</B></DIV>
<DIV>要在SkyEye中调试操作系统内核,首先必须使被调试内核能在SkyEye所模拟的开发板上正确运行。因此,正确编译待调试操作系统内核并配置SkyEye是进行内核调试的第一步。下面我们以SkyEye模拟基于Atmel
AT91X40的开发板,并运行μcLinux 2.6为例介绍SkyEye的具体调试方法。</DIV>
<DIV>I、安装交叉编译环境</DIV>
<DIV>先安装交叉编译器。尽管在一些资料中说明使用工具链arm-elf-tools-20040427.sh
,但是由于arm-elf-xxx与arm-linux-xxx对宏及链接处理的不同,经验证明使用arm-elf-xxx工具链在链接vmlinux的最后阶段将会出错。所以这里我们使用的交叉编译工具链是:arm-uclinux-tools-base-gcc3.4.0-20040713.sh,关于该交叉编译工具链的下载地址请参见[6]。注意以下步骤最好用root用户来执行。</DIV><BR><A
name=IDAAGAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl tmp]#chmod +x arm-uclinux-tools-base-gcc3.4.0-20040713.sh
[root@lisl tmp]#./arm-uclinux-tools-base-gcc3.4.0-20040713.sh
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>安装交叉编译工具链之后,请确保工具链安装路径存在于系统PATH变量中。</DIV>
<DIV>II、制作μcLinux内核</DIV>
<DIV>得到μcLinux发布包的一个最容易的方法是直接访问uClinux.org站点[7]。该站点发布的内核版本可能不是最新的,但你能找到一个最新的μcLinux补丁以及找一个对应的Linux内核版本来制作一个最新的μcLinux内核。这里,将使用这种方法来制作最新的μcLinux内核。目前(笔者记录编写此文章时),所能得到的发布包的最新版本是uClinux-dist.20041215.tar.gz。</DIV>
<DIV>下载uClinux-dist.20041215.tar.gz,文件的下载地址请参见[7]。</DIV>
<DIV>下载linux-2.6.9-hsc0.patch.gz,文件的下载地址请参见[8]。</DIV>
<DIV>下载linux-2.6.9.tar.bz2,文件的下载地址请参见[9]。</DIV>
<DIV>现在我们得到了整个的linux-2.6.9源代码,以及所需的内核补丁。请准备一个有2GB空间的目录里来完成以下制作μcLinux内核的过程。</DIV><BR><A
name=IDAOGAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl tmp]# tar -jxvf uClinux-dist-20041215.tar.bz2
[root@lisl uClinux-dist]# tar -jxvf linux-2.6.9.tar.bz2
[root@lisl uClinux-dist]# gzip -dc linux-2.6.9-hsc0.patch.gz | patch -p0
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>或者使用:</DIV><BR><A name=IDAWGAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl uClinux-dist]# gunzip linux-2.6.9-hsc0.patch.gz
[root@lisl uClinux-dist]patch -p0 < linux-2.6.9-hsc0.patch
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>执行以上过程后,将在linux-2.6.9/arch目录下生成一个补丁目录-armnommu。删除原来μcLinux目录里的linux-2.6.x(即那个linux-2.6.9-uc0),并将我们打好补丁的Linux内核目录更名为linux-2.6.x。</DIV><BR><A
name=IDA4GAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl uClinux-dist]# rm -rf linux-2.6.x/
[root@lisl uClinux-dist]# mv linux-2.6.9 linux-2.6.x
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>III、配置和编译μcLinux内核</DIV>
<DIV>因为只是出于调试μcLinux内核的目的,这里没有生成uClibc库文件及romfs.img文件。在发布μcLinux时,已经预置了某些常用嵌入式开发板的配置文件,因此这里直接使用这些配置文件,过程如下:</DIV><BR><A
name=IDAHHAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl uClinux-dist]# cd linux-2.6.x
[root@lisl linux-2.6.x]#make ARCH=armnommu CROSS_COMPILE=arm-uclinux- atmel_
deconfig
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>atmel_deconfig文件是μcLinux发布时提供的一个配置文件,存放于目录linux-2.6.x
/arch/armnommu/configs/中。</DIV><BR><A
name=IDAPHAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl linux-2.6.x]#make ARCH=armnommu CROSS_COMPILE=arm-uclinux-
oldconfig
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>下面编译配置好的内核:</DIV><BR><A
name=IDAXHAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
[root@lisl linux-2.6.x]# make ARCH=armnommu CROSS_COMPILE=arm-uclinux- v=1
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>一般情况下,编译将顺利结束并在Linux-2.6.x/目录下生成未经压缩的μcLinux内核文件vmlinux。需要注意的是为了调试μcLinux内核,需要打开内核编译的调试选项-g,使编译后的内核带有调试信息。打开编译选项的方法可以选择:</DIV>
<DIV>"Kernel debugging->Compile the kernel with debug
info"后将自动打开调试选项。也可以直接修改linux-2.6.x目录下的Makefile文件,为其打开调试开关。方法如下:。</DIV><BR><A
name=IDADIAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
CFLAGS += -g
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>最容易出现的问题是找不到arm-uclinux-gcc命令的错误,主要原因是PATH变量中没有包含arm-uclinux-gcc命令所在目录。在arm-linux-gcc的缺省安装情况下,它的安装目录是/root/bin/arm-linux-tool/,使用以下命令将路径加到PATH环境变量中。</DIV><BR><A
name=IDALIAZB><B></B></A><BR>
<TABLE cellSpacing=0 cellPadding=5 width="100%"
bgColor=#eeeeee border=1>
<TBODY>
<TR>
<TD><PRE><CODE>
Export PATH=$PATH:/root/bin/arm-linux-tool/bin
</CODE></PRE></TD></TR></TBODY></TABLE><BR>
<DIV>IV、根文件系统的制作</DIV>
<DIV>Linux内核在启动的时的最后操作之一是加载根文件系统。根文件系统中存放了嵌入式系统使用的所有应用程序、库文件及其他一些需要用到的服务。出于文章篇幅的考虑,这里不打算介绍根文件系统的制作方法,读者可以查阅一些其他的相关资料。值得注意的是,由配置文件skyeye.conf指定了装载到内核中的根文件系统。</DIV>
<DIV><A name=IDAUIAZB>3.2 使用SkyEye调试</A></DIV>
<DIV>编译完μcLinux内核后,就可以在SkyEye中调试该ELF执行文件格式的内核了。前面已经说过利用SkyEye调试内核与使用gdb调试运用程序的方法相同。</DIV>
<DIV>需要提醒读者的是,SkyEye的配置文件-skyeye.conf记录了模拟的硬件配置和模拟执行行为。该配置文件是SkyEye系统中一个及其重要的文件,很多错误和异常情况的发生都和该文件有关。在安装配置SkyEye出错时,请首先检查该配置文件然后再进行其他的工作。此时,所有的准备工作已经完成,就可以进行内核的调试工作了。</DIV>
<DIV><A name=IDA1IAZB>3.3使用SkyEye调试内核的特点和不足</A></DIV>
<DIV>在SkyEye中可以进行对Linux系统内核的全程调试。由于SkyEye目前主要支持基于ARM内核的CPU,因此一般而言需要使用交叉编译工具编译待调试的Linux系统内核。另外,制作SkyEye中使用的内核编译、配置过程比较复杂、繁琐。不过,当调试过程结束后无需重新制作所要发布的内核。</DIV>
<DIV>SkyEye只是对系统硬件进行了一定程度上的模拟,所以在SkyEye与真实硬件环境相比较而言还是有一定的差距,这对一些与硬件紧密相关的调试可能会有一定的影响,例如驱动程序的调试。不过对于大部分软件的调试,SkyEye已经提供了精度足够的模拟了。</DIV>
<DIV>SkyEye的下一个目标是和eclipse结合,有了图形界面,能为调试和查看源码提供一些方便。</DIV><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%"
border=0>
<TBODY>
<TR>
<TD><IMG height=1 alt=""
src="Linux 系统内核的调试.files/blue_rule.gif"
width="100%"></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 align=right>
<TBODY>
<TR align=right>
<TD></TD></TR></TBODY></TABLE><BR><BR>
<DIV><A name=IDADJAZB>4. 使用UML调试Linux内核</A></DIV>
<DIV>User-mode
Linux(UML)简单说来就是在Linux内运行的Linux。该项目是使Linux内核成为一个运行在
Linux 系统之上单独的、用户空间的进程。UML并不是运行在某种新的硬件体系结构之上,而是运行在基于
Linux
系统调用接口所实现的虚拟机。正是由于UML是一个将Linux作为用户空间进程运行的特性,可以使用UML来进行操作系统内核的调试。有关UML的介绍请查阅参考资料[10]、[12]。</DIV>
<DIV><A name=IDAJJAZB>4.1 UML的安装与调试</A></DIV>
<DIV>UML的安装需要一台运行Linux
2.2.15以上,或者2.3.22以上的I386机器。对于2.6.8及其以前版本的UML,采用两种形式发布:一种是以RPM包的形式发布,一种是以源代码的形式提供UML的安装。按照UML的说明,以RPM形式提供的安装包比较陈旧且会有许多问题。以二进制形式发布的UML包并不包含所需要的调试信息,这些代码在发布时已经做了程度不同的优化。所以,要想利用UML调试Linux系统内核,需要使用最新的UML
patch代码和对应版本的Linux内核编译、安装UML。完成UML的补丁之后,会在arch目录下产生一个um目录,主要的UML代码都放在该目录下。</DIV>
<DIV>从2.6.9版本之后(包含2.6.9版本的Linux),User-Mode
Linux已经随Linux内核源代码树一起发布,它存放于arch/um目录下。</DIV>
<DIV>编译好UML的内核之后,直接使用gdb运行已经编译好的内核即可进行调试。</DIV>
<DIV><A name=IDARJAZB>4.2使用UML调试系统内核的特点和不足</A></DIV>
<DIV>目前,用户模式 Linux
虚拟机也存在一定的局限性。由于UML虚拟机是基于Linux系统调用接口的方式实现的虚拟机,所以用户模式内核不能访问主机系统上的硬件设备。因此,UML并不适合于调试那些处理实际硬件的驱动程序。不过,如果所编写的内核程序不是硬件驱动,例如Linux文件系统、协议栈等情况,使用UML作为调试工具还是一个不错的选择。</DIV><BR>
<TABLE cellSpacing=0 cellPadding=0 width="100%"
border=0>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -