收藏 分销(赏)

第9章基于ARM9和Linux嵌入式系统设计.ppt

上传人:天**** 文档编号:14651774 上传时间:2026-10-25 格式:PPT 页数:136 大小:816.04KB 下载积分:10 金币
下载 相关
第9章基于ARM9和Linux嵌入式系统设计.ppt_第1页
第1页 / 共136页
第9章基于ARM9和Linux嵌入式系统设计.ppt_第2页
第2页 / 共136页


点击查看更多>>
资源描述
,单击此处编辑母版文本样式,第二级,第三级,第四级,第五级,*,第9章 基于ARM9和Linux嵌入式系统设计,单击此处编辑母版文本样式,第二级,第三级,第四级,第七章 串行口,此处编辑母版标题样式,第9章 基于ARM9和Linux嵌入式系统设计,9.1 嵌入式Linux的开发环境,9.2 Linux开发工具的使用,9.3 GNU make命令和makefile 文件,9.4 嵌入式Linux引导程序,9.5 嵌入式Linux 下程序调试应用举例,9.1 嵌入式Linux的开发环境,9.1.1,嵌入式,Linux,开发环境建立,嵌入式Linux 开发环境有几个方案:,(1)在,WINDOWS,下安装,Linux,虚拟机后,目前大多情况下使用,VWare,软件;,(2)直接安装,Linux,操作系统。,9.1.2 嵌入式Linux开发的一般过程,1.,了解硬件,;,2.,准备需要使用的,Linux,工具以及其他工具,;,3.,安排内存地址,;,4.,编写启动代码和机器相关代码,;,5.,编写驱动程序;,6,.,C,库、,GUI,和系统程序的移植;,7,.,调试.,9.2 Linux开发工具的使用,9.2.1 Linux开发工具GNU gcc的使用,1.GCC简介,GCC是GNU Compiler Collection的简称,GCC是Linux平台下最常用的编译程序,是Linux平台编译器的事实标准。,GCC支持的体系结构有40余种,常见的有x86系列、Arm、PowerPC等。同时,GCC还能运行在不同的操作系统上,如Linux、Solaris、Windows等。,GCC除了支持C语言外,还支持多种其他语言,例如C+、Ada、Java、Objective-C、Fortram、Pascal等。,2.GCC常用模式及选项,gcc最基本的用法是:,gcc options file.,其中option是以“-”开始的各种选项,file是相关的文件名。在使用gcc的时,必须给出必要的选项和文件名。gcc的整个编译过程分别是:预处理、编译,汇编和链接。,例:假设全部的源代码都在一个文件test.c中。,$gcc-o test,此命令是把源文件test.c直接编译成可执行程序test。,$gcc-c test.c,此命令是把源文件test.c编译成不可执行目标文件test.o。默认情况下,生成的目标文件名为test.o,但也可以为输出文件指定名称,如下所示:,$gcc-c test.c o mytest.o,此命令是把源文件test.c编译成不可执行目标文件my,test.o。,下面的命令将同时编译3个源文件,即first.c、second.c和 third.c,然后将它们连接成一个可执行程序test。命令如下:,$gcc-o test first.c second.c third.c,3其他常用选项的使用,$gcc test.c I./inc-o test,此命令告诉GCC包含文件存放在./inc 目录下,在当前目录的上一级。如果在编译时需要的包含文件存放在多个目录下,可使用多个-I 来指定各个目录。如:,$gcc test.c I./inc I././inc2-o test,此命令指出了另一个包含子目录inc2,较之前目录它还要在再上两级才能找到。另外,还可在编译命令行中定义符号常量。可简单的在命令行中使用-D选项即可,如下例所示:,$gcc D TEST_CONFIGURATION test.c-o test,上面的命令与在源文件中加入下列命令是等效的:,#define TEST_CONFIGURATION,3,其他常用选项的使用,$gcc test.c I./inc-o test,此命令告诉,GCC,包含文件存放在,./inc,目录下,在当前目录的上一级。若在编译时需要的包含文件存放在多个目录下,,可使用多个,-I,来指定各个目录:,$gcc test.c I./inc I././inc2-o test,上面命令告诉,GCC,包含文件存放在,./inc,目录下,在当前目录的上一级。若在编译时需的包含文件存放在多个目录下,可使用多个,-I,来指定各个目录:,$gcc test.c I./inc I././inc2-o test,这里指出了另一个包含子目录,inc2,,较之前目录它还要在再上两级才能找到,.,另外,我们还可以在编译命令行中定义符号常量。为此,我们可以简单的 在命令行中使用,-D,选项即可,如下例所示:,$gcc-DTEST_CONFIGURATION test.c-o test,上面的命令与在源文件中加入下列命令是等效的:,#define TEST_CONFIGURATION,4.警告功能,当GCC在编译过程中检查出错误,则中止编译;但检测到警告时却能继续编译生成可执行程序。,在众多的警告选项之中,最常用的是-Wall选项。该选项能发现程序中一系列的常见错误警告,举例如下:,$gcc-Wall test.c-o test,该选项相当于同时使用了下列所有的选项:,unused-function:遇到仅声明过但尚未定义的静态函数时发出警告。,unused-label:遇到声明过但不使用的标号的警告。,unused-parameter:从未用过的函数参数的警告。,9.2.2 GDB调试器简介,Linux系统中包含了GNU 调试程序gdb,用来调试C和 C+程序的调试器。gdb 提供如下功能:,运行程序,设置所有的能影响程序运行的参数和环境。,控制程序在指定的条件下停止运行。,当程序停止时,可以检查程序的状态。,修改程序的错误,并重新运行程序。,动态监视程序中变量的值。,可以单步执行代码,观察程序的运行状态。,1gdb的启动,在终端窗口中,有两种方法运行gdb,即在终端窗口的命令行中直接输入gdb命令或gdb filename命令运行gdb。,方法1:,先启动gdb后执行file filename命令。即,gdb,file filename,执行上述两条命令就可启动gdb,并装入可执行的程序filename。,方法2:,启动gdb的同时装入可执行的程序。即,gdb filename,其中,filename是要调试的可执行文件。这和启动gdb后执行file filename命令效果完全一样。,启动gdb后,就可以使用gdb的命令调试程序。,2gdb的基本命令,gdb中的命令分为以下几类:,工作环境相关命令、设置断点与恢复命令、源代码查看命令、查看运行数据相关命令及修改运行参数命令。,gdb的命令可以通过help命令进行查找命令所属的种类(class),可以从相关class找到相应命令。如下所示:,(gdb)help 此命令可列出命令的种类。,(gdb)help data 此命令查找data类种的命令,并列出data类种的所有命令。,(gdb)help call 此命令查找call命令。,直接键入“help command”来查看命令。,(1)工作环境相关命令,(2)设置断点与恢复命令,(3)gdb中源码查看相关命令,(4)gdb中查看运行数据相关命令,(5)其他gdb命令,run命令:执行当前被调试的程序。,kill命令:停止正在调试的应用程序。,watch命令:设置监视点,监视表达式的变化。,awatch命令:设置读写监视点。当要监视的表达式被读或写时将应用程序挂起。它的语法与watch命令相同。,rwatch命令:设置读监视点,当监视表达式被读时将程序挂起,等侍调试。此命令的语法与watch相同。,info break命令:显示当前断点列表,包括每个断点到达的次数。,info files命令:显示调试文件的信息。,info func命令:显示所有的函数名。,info local命令:显示当前函数的所有局部变量的信息。,info prog命令:显示调试程序的执行状态。,Shell命令:执行Linux Shell命令。,make命令:不退出gdb而重新编译生成可执行文件。,Quit命令:退出gdb。,(6)gdb中修改运行参数相关命令,gdb可修改运行时的参数,并使该变量按照用户当前输入的值继续运行。,方法为:在单步执行的过程中,键入命令:,set 变量设定值,在此之后,程序就会按照该设定的值运行了。,特别注意,在gcc编译选项中一定要加入”-g”。只有在代码处于“运行”或“暂停”状态时才能查看变量值,设置断点后程序在指定行之前停止。,9.3 GNU make命令和makefile 文件,显式规则,隐晦规则,文件指示。其包括3个部分,一个是在一个Makefile中引用另一个Makefile,就像C语言中的include一样;另一个是指根据某些情况指定Makefile中的有效部分,就像C语言中的预编译#if一样;还有就是定义一个多行的命令。,注释。Makefile中只有行注释,用“#”字符,在Makefile中的命令,必须要以Tab键开始。,GNU的make工作时的执行步骤如下:,1.读入所有的Makefile。,2.读入被include的其它Makefile。,3.初始化文件中的变量。,4.推导隐晦规则,并分析所有规则。,5.为所有的目标文件创建依赖关系链。,6.根据依赖关系,决定哪些目标要重新生成。,7.执行生成命令。,9.3.1 Makefile文件的规则,1Makefile书写规则,Makefile文件含有一系列的规则,规则内容:,一个目标(target),即make最终需要创建的文件,如可执行文件和目标文件;目标也可以是要执行的动作,如clean。,一个或多个依赖文件(dependency)列表,通常是编译目标文件所需要的其他文件。,一系列命今(command),是make执行的动作,通常是把指定的相关文件编译成目标文件的编译命令,每个命令占一行,且每个命令行起始字符必须为TAB字符。,Makefile规则的一般形式如下:,target:dependency dependency,(tab),例如:有以下的Makefile文件:,test:prog.o code.o,gcc o test prog.o code.o,prog.o:prog.c prog.h code.h,gcc c prog.c o prog.o,code.o:code.c code.h,gcc c code.c o code.o,clean:,rm f*.o,一般情况下,调用make命令可输入:,#make target,target是Makefile文件中定义的目标之一,如果省略target,make就将生成Makefile文件中定义的第一个目标。对于上面Makefile的例子,单独的一个make命令等价于:,#make test,因为test是Makefile文件中定义的第一个目标,make首先将其读入,然后从第一行开始执行,把第一个目标test作为它的最终目标,所有后面的目标的更新都会影响到test的更新。,内核源代码中Makefile被分布在目录树中,与Makefile直接相关的文件有配置文件,.config,和规则文件,Rules.make,。顶层Makefile是整个内核配置、编译的总体控制文件。在顶层Makefile中的语句:,include arch/$(ARCH)/Makefile,包含了特定CPU体系结构下的,Makefile,,这个,Makefile,中包含了平台相关的信息。配置文件.config包含由用户选择项,用来存放内核配置后的结果(如,make config,)。位于各种CPU体系目录下的,Makefile,,比如,drivers/Makefile,,负责所在子目录下源代码的管理。规则文件,Rules.make,,则被所有的,Makefile,使用。,用户通过make config配置后,产生了.config。顶层Makefile读入.config中的配置选择。顶层Makefile有两个主要的任务:产生压缩的内核镜像vmlinux文件和内核模块module。为了达到此目的,顶层Makefile递归的进入到内核的各个子目录中,分别调用位于子目录中的Makefile。至于到底进入哪些子目录,取决于内核的配置。位于各个子目录下的Makefile同样也根据.config给出的配置信息,构造出当前配置下需要的源文件列表,并在文件的最后有include$(TOPDIR)/Rules.make。,2.在规则中使用通配符,make支持3种通配符:“*”,“?”和“.”。,波浪号(“”)字符在文件名中有特殊的用途。如“test”表示当前用户的$HOME目录下的test目录。而“hchen/test”则表示用户hchen的宿主目录下的 test目录。通配符“*.c”表示所有以后缀为c的文件。,例如:,print:*.c,lpr-p$?,touch print,该例说明目标print依赖于所有的.c文件。其中的“$?”是一个自动化变量。,3.伪目标,伪目标又称假想目标,如:,clean:,rm*.o temp,这里并不生成“clean”这个文件。“伪目标”并不是一个文件,只是一个标签,由于“伪目标”不是文件,所以make无法生成它的依赖关系和决定它是否要执行。,可使用“make clean”来使用该目标。,如果你的Makefile需要生成若干个可执行文件,可把所有的目标文件都写在一个Makefile中,可声明了一个“all”的伪目标。,声明了一个“all”的伪目标,例如:,all:prog1 prog2 prog3,prog1:prog1.o utils.o,cc-o prog1 prog1.o utils.o,prog2:prog2.o,cc-o prog2 prog2.o,prog3:prog3.o sort.o utils.o,cc-o prog3 prog3.o sort.o utils.o,9.3.2 Makefile文件中隐含规则,1常用的隐含规则,编译C程序的隐含规则:.o的目标的依赖目标会自动推导为.c,并且其生成命令是,$(CC)c$(CPPFLAGS)$(CFLAGS)。,编译C+程序的隐含规则:.o的目标的依赖目标会自动推导为.cc或是.C,并且其生成命令是$(CXX)c$(CPPFLAGS)$(CFLAGS)。(建议使用.cc作为C+源文件的后缀,而不是.C),汇编和汇编预处理的隐含规则:,.o的目标的依赖目标会自动推导为.s,默认使用编译器as,并且其生成命令是:$(AS)$(ASFLAGS)。.s的目标的依赖目标会自动推导为.S,默认使用C预编译器cpp,并且其生成命令是:$(AS)$(ASFLAGS)。,链接Object文件的隐含规则,目标依赖于.o,通过运行C 的编译器来运行链接程序生成(一般是ld),其生成命令是:$(CC)$(LDFLAGS).o$(LOADLIBES)$(LDLIBS)。这个规则对于只有一个源文件的工程有效,同时也对多个Object文件(由不同的源文件生成)也有效。,2隐含规则使用的变量,(1)关于命令的变量。,AR:函数库打包程序。默认命令是ar。,AS:汇编语言编译程序。默认命令是as。,CC:C语言编译程序。默认命令是cc。,CXX:C+语言编译程序。默认命令是g+。,CPP:C程序的预处理器(输出是标准输出设备)。默认命令是$(CC)E。,RM:删除文件命令。默认命令是rm f。,(2)关于命令参数的变量,以下变量都是相关上面的命令的参数。若没有指明其默认值,则其默认值都是空。,ARFLAGS:函数库打包程序AR命令的参数。默认值是,rv,。,ASFLAGS:汇编语言编译器参数。(当明显地调用“.s”或“.S”文件时)。,CFLAGS:C语言编译器参数。,CXXFLAGS:C+语言编译器参数。,CPPFLAGS:C预处理器参数。(C 和 Fortran 编译器也会用到)。,FFLAGS:Fortran语言编译器参数。,GFLAGS:SCCS get程序参数。,LDFLAGS:链接器参数。(如:ld),3自动化变量,常用的自动化变量如下。,$:表示规则中的目标文件集。在模式规则中,如果有多个目标,那么,$就是匹配于目标中模式定义的集合。,$%:仅当目标在函数库文件中,表示规则中的目标成员名。例如,如果一个目标是,foo.a(bar.o),那么,$%就是bar.o,$就是foo.a。如果目标不是函数库文件(Unix下是.a,Windows下是.lib),那么,其值为空。,$:依赖目标中的第一个目标名字。如果依赖目标是以模式(即%)定义的,那么$1:2:4,ChangeMPllValue(0 xa1,0 x3,0 x1);/时钟值FCLK=202.8MHz,Port_Init();,Isr_Init();,Uart_Init(0,115200);,Uart_Select(0);,while(1),Uart_Printf(nnSMDK2410 Board(MCU S3C2410)Example Program Ver 1.0(20020521)FCLK=%d Hznn,FCLK);,9.4.2 VIVI简介,VIVI是韩国Mizi公司开发的BootLoader,可用于ARM9处理器的引导。VIVI利用串行通信为用户提供接口。它有如下作用:,把内核(kernel)从flash复制到RAM,然后启动它;,初始化硬件;,下载程序并写入flash(通常由串口或者网口先把内核下载到RAM中,然后写入flash);,检测目标板(bootloader会有一些简单的代码用以测试目标板硬件的好坏)。,1.VIVI的命令,(1)load命令,将二进制文件载入到Flash或者RAM,命令格式:,load|,其中:描述装载位置,有flash和ram两种选项;,或 描述装载的地址,如果有提前定义的mtd分区信息,可以只输入分区名称,否则需要指定地址和大小;参数 确定文件的传输协议,常采用的选项“x”用来指定采用xmodem协议。,例如:vivi load flash kernel x,装载压缩映像文件zImage到flash存储器中,地址是kernel分区,并采用xmodem传输协议。,例如:vivi load flash 0 x80000 0 xc0000 x。,(2)part命令,part命令用来操作MTD分区信息,比如显示、增加、删除、复位、保存MTD分区等。,part show:显示mtd分区信息。,part add :增加新的mtd分区,其中为新mtd分区名称,是mtd器件的偏移,表示mtd分区的大小,表示分区类型,可选项有JFFS2、LOCKED和BONFS。,part del:删除一个mtd分区。,part reset:恢复mtd 分区为默认值。,part save:在flash中永久保存参数值和分区信息。,(3)param命令,param命令用来设置或者查看参数。,例如:改变linux command line,使用,vivi param set linux_cmd_line“you wish.”。,也可以改变引导程序启动的时间,使用,vivi param set boot_delay 100000实现。,(4)boot命令,boot命令用来引导存储在flash存储器或者ram中的linux内核。命令格式:,boot|,参数 设定存储linux内核映像的位置,可选项有ram、nor和smc。,参数 或 描述存储内核的地址,如果有提前定义的mtd分区信息,可以只输入分区名称,否则需要指定地址和大小。,例如:vivi boot nor 0 x80000表示从flash存储器中读出linux内核,偏移是0 x80000。,(5)flash命令,flash命令是存储器管理命令,,例如:,flash erase|,表示擦除flash存储器。,2VIVI的目录树,VIVI的目录如图9.1所示,2VIVI的目录树,VIVI包括的目录具体如下:,arch:包括所有VIVI支持的目标板的子目录。,Documentation:存放了许多文档,包括VIVI使用指南。,drivers:其中包括了引导内核所需的MTD设备和串口驱动程序。MTD目录下分maps、nand和nor三个目录,实现对Nand Flash和Nor Flash的读写控制。Serial目录下的文件实现对串口的控制,并支持xmodem和ymodem协议。,include:头文件的公共目录,其中有S3C2410.h。Platform/smdk2410.h定义了与目标板相关的资源配置参数,修改波特率、引导参数和物理内存映射等参数即可配置目标板。,init:此目录只有main.c和version.c两个文件。与普通的C程序一样,VIVI将从main函数开始执行。,lib:一些平台公共的接口代码,比如,time.c里的udelay()和mdelay()。,scripts:此目录存放了配置所需的脚本文件,如Menuconfig和Configure文件,以方便对VIVI的配置。,9.5 嵌入式Linux 下程序调试应用举例,9.5.1 Linux宿主机下的应用程序调试,下面用一个例子来介绍Linux开发工具GNU gcc的编译和GNU gdb调试器的使用。,1,gcc,编译器的使用,假定例中有4个文件,分别是hello.h、starfun.h、hello.c和star.c。使用Vi编辑器完成hello.h、starfun.h、hello.c和star.c 4个文件的内容输入。,Starfun.h 文件内容如下:,/*starfun.h*/,#ifndef STARFUN_H,#define STARFUN_H,#define NUM 4,#define NUMBER 3,int star1(),int i,j,k;,for(k=1;k=NUM;+k),for(i=1;i=(NUM-k);+i),printf();,for(j=1;j=0;-k),for(i=1;i=(NUMBER-k+1);+i),printf();,for(j=1;j/usr/lib/libhello.so(0 x4002d000),libc.so.6=/lib/tls/libc.so.6(0 x42000000),/lib/ld-linux.so.2=/lib/ld-linux.so.2(0 x40000000),(5)运行可执行的目标程序,rootlocalhost 01_hello#./mystar,可得与第一种方法同样的结果。,第五种方法:使用静态库完成编译,在使用静态库编译之前应先删除已有对应的目标文件和库文件,然后再使用静态库编译,,步骤如下:,(,1,)删除已有对应的目标文件和库文件,rootlocalhost 01_hello#rm*.o,rm:是否删除一般文件hello.o?y,rootlocalhost 01_hello#rm mystar,rm:是否删除一般文件mystar?y,rootlocalhost 01_hello#,rootlocalhost 01_hello#rm libhello.*,(2)把hello.c编译连接成静态库,rootlocalhost 01_hello#gcc-c hello.c-o hello.o,rootlocalhost 01_hello#ar-rc libhello.a hello.o,(3)静态库与其他待编译的源程序一同编译连接成可执行的目标程序,rootlocalhost 01_hello#gcc star.c libhello.a -o mystar,(4)运行可执行的目标程序,rootlocalhost 01_hello#./mystar,可得与第一种方法同样的结果。,2Linux宿主机下的GNU gdb调试器的使用,下面通过用gdb调试一个语法上没有错误,但功能上有错误的程序来说明gdb的使用。,代码示例 eg1.c,#include,int wib(int no1,int no2),int result,diff;,diff=no1-no2;,result=no1/diff;,return result;,int main(int argc,char*argv),int value,div,result,i,total;,value=10;,div=6;,total=0;,for(i=0;i 10;i+),result=wib(value,div);,total+=result;,div+;,value-;,printf(%d wibed by%d equals%dn,value,div,total);,return 0;,这个程序将运行 10 次 for 循环,使用 wib()函数计算出累积值,最后打印出结果。使用 gcc-g eg1.c-o eg1 进行编译,并用 gdb eg1 启动 gdb。使用 run 运行程序可能会产生以下消息:,Program received signal SIGFPE,Arithmetic exception.,0 x80483ea in wib(no1=8,no2=8)at eg1.c:7,7 result=no1/diff;,(gdb),gdb 指出在程序第 7 行发生一个算术异常,通常它会打印这一行以及 wib()函数的自变量值。要查看第 7 行前后的源代码,请使用 list 命令,它通常会打印 10 行。再次输入 list(或者按回车重复上一条命令)将列出程序的下 10 行。从 gdb 消息中可以看出,第 7 行中的除法运算出了错,程序在这一行中将变量 no1 除以 diff。,要查看变量的值,使用 gdb print 命令并指定变量名。输入 print no1 和 print diff,可以相应看到 no1 和 diff 的值,结果如下:,(gdb)print no1,$5=8,(gdb)print diff,$2=0,gdb 指出 no1 等于 8,diff 等于 0。根据这些值和第 7 行中的语句,我们可以推断出算术异常是由除数为 0 的除法运算造成的。清单显示了第 6 行计算的变量 diff,我们可以打印 diff 表达式(使用 print no1-no2 命令),来重新估计这个变量。gdb 告诉我们 wib 函数的这两个自变量都等于 8,于是我们要检查调用 wib()函数的 main()函数,以查看这是在什么时候发生的。在允许程序自然终止的同时,我们使用 continue 命令告诉 gdb 继续执行。,(gdb)continue,Continuing.,Program terminated with signal SIGFPE,Arithmetic exception.,The program no longer exists.,(1)使用断点,为了查看在 main()中发生了什么情况,可以在程序代码中的某一特定行或函数中设置断点,这样 gdb 会在遇到断点时中断执行。可以使用命令 break main 在进入 main()函数时设置断点,或者可以指定其它任何感兴趣的函数名来设置断点。然而,我们只希望在调用 wib()函数之前中断执行。输入 list main 将打印从 main()函数开始的源码清单,再次按回车将显示第 21 行上的 wib()函数调用。要在那一行上设置断点,只需输入 break 21。,gdb 将发出以下响应:,(gdb)break 21,Breakpoint 1 at 0 x8048428:file eg1.c,line 21.,以显示它已在我们请求的行上设置了 1 号断点。run 命令将从头重新运行程序,直到 gdb 中断为止。发生这种情况时,gdb 会生成一条消息,指出它在哪个断点上中断,以及程序运行到何处:,Breakpoint 1,main(argc=1,argv=0 xbffff954)at eg1.c:21,21 result=wib(value,div);,发出 print value 和 print div 将会显示在第一次调用 wib()时,变量分别等于 10 和 6,而 print i 将会显示 0。幸好,gdb 将显示所有局部变量的值,并使用 info locals 命令保存大量输入信息,gdb 将发出以下响应:,(gdb)break 21,Breakpoint 1 at 0 x8048428:file eg1.c,line 21.,以显示它已在我们请求的行上设置了 1 号断点。run 命令将从头重新运行程序,直到 gdb 中断为止。发生这种情况时,gdb 会生成一条消息,指出它在哪个断点上中断,以及程序运行到何处:,Breakpoint 1,main(argc=1,argv=0 xbffff954)at eg1.c:21,21 result=wib(value,div);,发出 print value 和 print div 将会显示在第一次调用 wib()时,变量分别等于 10 和 6,而 print i 将会显示 0。幸好,gdb 将显示所有局部变量的值,并使用 info locals 命令保存大量输入信息,从以上的调查中可以看出,当 value 和 div 相等时就会出现问题,因此输入 continue 继续执行,直到下一次遇到 1 号断点。对于这次迭代,info locals 显示了 value=9 和 div=7。,与其再次继续,还不如使用 next 命令单步调试程序,以查看 value 和 div 是如何改变的。gdb 将响应:,(gdb)next,22 total+=result;,再按两次回车将显示加法和减法表达式:,(gdb),23 div+;,(gdb),24 value-;,再按两次回车将显示第 21 行,wib()调用。info locals 将显示目前 div 等于 value,这就意味着将发生问题。如果有兴趣,可以使用 step 命令(与 next 形成对比,next 将跳过函数调用)来继续执行 wib()函数,以再次查看除法错误,然后使用 next 来计算 result。,完成调试后,可以使用 quit 命令退出 gdb。由于程序仍在运行,这个操作会终止它,gdb 将提示确认。,(2)更多断点和观察点的设置,在第 21 行中设置断点。,要设置条件,可以在定义断点时指定“break,if”。,将 eg1 再次装入 gdb,并输入:,(gdb)break 21 if value=div,Breakpoint 1 at 0 x8048428:file eg1.c,line 21.,如果已经在第 21 行中设置了断点,如 1 号断点,则可以使用 condition 命令来代替在断点上设置条件:,(gdb)condition 1 value=div,使用 condition 命令时,如果指定断点编号但又不指定表达式,可以将断点设置成无条件断点,例如,condition 1 就将 1 号断点设置成无条件断点。,要查看当前定义了什么断点及其条件,请发出命令 info break:,(gdb)info break,Num Type Disp Enb Address What,1 breakpoint keep y 0 x08048428 in main at eg1.c:21,stop only if value=div,breakpoint already hit 1 time,下面三个命令可以对断点操作:,禁止断点,命令:,disable,启用断点命令:,enable breakpoint number,删除断点命令:,delete,设置监视点:,监视点将中断程序执行,须在表达式中所使用的变量在作用域中时设置监视点。要获取作用域中的 value 和 div,可以在 main 函数上设置断点,然后运行程序,当遇到 main()断点时设置监视点。重新启动 gdb,并装入 eg1,然后输入:,(gdb)break main,Breakpoint 1 at 0 x8048402:file eg1.c,line 15.,(gdb)run,.,Breakpoint 1,main(argc=1,argv=0 xbffff954)at eg1.c:15,15 value=10;,要了解 div 何时更改,可以使用 watch div,但由于要在 div 等于 value 时中断,那么应输入:,如果继续执行,那么当表达式 div=value 的值从 0(假)变成 1(真)时,gdb 将中断:,(gdb)continue,Continuing.,Hardware watchpoint 2:div=value,Old value=0,New value=1,main(argc=1,argv=0 xbffff954)at eg1.c:19,19 for(i=0;i 10;i+),info locals 命令将验证“value”是否确实等于“div”(再次声明,是 8)。,info watch 命令将列出已定义的监视点和断点(此命令等价于 info break),而且可以使用与断点相同的语法来启用、禁用和删除监视点。,(3)core 文件,gdb 可装入 core 文件,检查程序中止之前的状态。,在 gdb 外运行示例程序eg1将会导致核心信息转储:,$./eg1,Floating point exception(core dumped),要使用 core 文件启动 gdb,在 shell 中发出命令 gdb eg1 core 或 gdb eg1-c core。gdb 将装入 core 文件,eg1 的程序清单,显示程序是如何终止的,并显示非常类似于我们刚才在 gdb 下运行程序时看到的消息:,.,Core was generated by./eg1.,Program terminated with signal 8,Floating point exception.,.,#0 0 x80483ea in wib(no1=8,no2=8)at eg1.c:7,7 result=no1/diff;,此时,可以发出 info locals、print、info args 和 list 命令来查看引起除数为零的值。,(4)堆栈跟踪,要打印堆栈,发出命令 bt(backtrace的缩写:,(gdb)bt,#0 0 x80483ea in wib(no1=8,no2=8)at eg1.c:7,#1 0 x8048435 in main(argc=1,argv=0 xbffff9c4)at eg1.c:21,此结果显示了在 main()的第 21 行中调用了函数 wib()(只要使用 list 21 就能证实这一点),而且 wib()在 0 号帧中,main()在 1 号帧中。由于 wib()在 0 号帧中,那么它就是执行程序时发生算术错误的函数。,info locals 命令,gdb 会打印出当前帧中的局部变量,缺省情况下,这个帧中的函数就是被中断的函数(0 号帧)。可以使用命令 frame 打印当前帧。要查看 main 函数(在 1 号帧中)中的变量,可以发出 frame 1 切换到 1 号帧,然后发出 info locals 命令:,(gdb)frame 1,#1 0 x8048435 in main(argc=1,argv=0 xbffff9c4)at eg1.c:21,21 result=wib(value,div);,(gdb)info locals,value=8,div=8,result=4,i=2,total=6,此信息显示了在第三次执行 for 循环时(i 等于 2)发生了错误,此时 value 等于 div。,(5)连接到其它进程,除了调试 core 文件或程序之外,gdb 还可以连接到已经运行的进程(它的程序已经过编译,并加入
展开阅读全文

开通  VIP、SVIP  下载更划算
下载10份以上建议开通 VIP 会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 学术论文 > 其他

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        关注我们

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服