linux教程之把握 Linux 调试手艺
开发linux发行版的人都是通读过linux内核代码,对linux原理极其精通的人。谢谢收躲http://www.qqread.com/linux/2006/06/f775123061.html
在Linux上找出并办理程序毛病的次要办法
您能够用各类办法来监控运转着的用户空间程序:能够为其运转调试器并单步伐试该程序,增加打印语句,大概增加工具来剖析程序。本文形貌了几种能够用来调试在Linux上运转的程序的办法。
我们将回忆四种调试成绩的情形,这些成绩包含段毛病,内存溢出和泄露,另有挂起。
本文会商了四种调试Linux程序的情形。在第1种情形中,我们利用了两个有内存分派成绩的样本程序,利用MEMWATCH和YetAnotherMallocDebugger(YAMD)工具来调试它们。在第2种情形中,我们利用了Linux中的strace有用程序,它可以跟踪体系挪用和旌旗灯号,从而找出程序产生毛病的中央。在第3种情形中,我们利用Linux内核的Oops功效来办理程序的段毛病,并向您展现怎样设置内核源代码级调试器(kernelsourceleveldebugger,kgdb),以利用GNU调试器(GNUdebugger,gdb)来办理不异的成绩;kgdb程序是利用串行毗连的Linux内核远程gdb。在第4种情形中,我们利用Linux上供应的把戏键控按次(magickeysequence)来显现激发挂起成绩的组件的信息。
罕见调试办法
当您的程序中包括毛病时,极可能在代码中某处有一个前提,您以为它为真(true),但实践上是假(false)。找堕落误的历程也就是在找堕落误后颠覆之前一向确信为真的某个前提历程。
以下几个示例是您大概确信建立的前提的一些范例:
在源代码中的某处,某变量有特定的值。
在给定的中央,某个布局已被准确设置。
关于给定的if-then-else语句,if部分就是被实行的路径。
当子例程被挪用时,该例程准确地吸收到了它的参数。
找堕落误也就是要断定上述一切情形是不是存在。假如您确信在子例程被挪用时某变量应当有特定的值,那末就反省一下情形是不是云云。假如您信任if布局会被实行,那末也反省一下情形是不是云云。一般,您的假定城市是准确的,但终极您会找到与假定不符的情形。了局,您就会找动身生毛病的中央。
调试是您没法回避的义务。举行调试有良多种办法,好比将动静打印到屏幕上、利用调试器,或只是思索程序实行的情形并细心地推测成绩地点。
在修改成绩之前,您必需找出它的泉源。举例来讲,关于段毛病,您必要懂得段毛病产生在代码的哪一行。一旦您发明了代码中堕落的行,请断定该办法中变量的值、办法被挪用的体例和关于毛病怎样产生的具体情形。利用调试器将使找出一切这些信息变得很复杂。假如没有调试器可用,您还可使用别的的工具。(请注重,产物情况中大概其实不供应调试器,并且Linux内核没有内建的调试器。)
有用的内存和内核工具
您可使用Linux上的调试工具,经由过程各类体例跟踪用户空间和内核成绩。请利用上面的工具和手艺来构建和调试您的源代码:
用户空间工具:
内存工具:MEMWATCH和YAMD
strace
GNU调试器(gdb)
把戏键控按次
内核工具:
内核源代码级调试器(kgdb)
内建内核调试器(kdb)
Oops
本文将会商一类经由过程野生反省代码不简单找到的成绩,并且此类成绩只在很少见的情形下存在。内存毛病一般在多种情形同时存在时呈现,并且您偶然只能在部署程序以后才干发明内存毛病。
第1种情形:内存调试工具
C言语作为Linux体系上尺度的编程言语赐与了我们对静态内存分派很年夜的把持权。但是,这类自在大概会招致严峻的内存办理成绩,而这些成绩大概招致程序溃散或随工夫的推移招致功能升级。
内存泄露(即malloc()内存在对应的free()挪用实行后永不被开释)弛缓冲区溢出(比方对之前分派到某数组的内存举行写操纵)是一些罕见的成绩,它们大概很难检测到。这一部分将会商几个调试工具,它们极年夜地简化了检测和找出内存成绩的历程。
MEMWATCH
MEMWATCH由JohanLindh编写,是一个开放源代码C言语内存毛病检测工具,您能够本人下载它(请参阅本文前面部分的参考材料)。只需在代码中增加一个头文件并在gcc语句中界说了MEMWATCH以后,您就能够跟踪程序中的内存泄露和毛病了。MEMWATCH撑持ANSIC,它供应了局日记记录,能检测两重开释(double-free)、毛病开释(erroneousfree)、没有开释的内存(unfreedmemory)、溢出和下溢等等。
清单1.内存样本(test1.c)
#include
#include
#include"memwatch.h"
intmain(void)
{
char*ptr1;
char*ptr2;
ptr1=malloc(512);
ptr2=malloc(512);
ptr2=ptr1;
free(ptr2);
free(ptr1);
}
清单1中的代码将分派两个512字节的内存块,然后指向第一个内存块的指针被设定为指向第二个内存块。了局,第二个内存块的地点丧失,从而发生了内存泄露。
如今我们编译清单1的memwatch.c。上面是一个makefile示例:
test1
gcc-DMEMWATCH-DMW_STDIOtest1.cmemwatch
c-otest1
当您运转test1程序后,它会天生一个关于泄露的内存的呈报。清单2展现了示例memwatch.log输入文件。
清单2.test1memwatch.log文件
MEMWATCH2.67Copyright(C)1992-1999JohanLindh
...
double-free:<4>test1.c(15),0x80517b4wasfreedfromtest1.c(14)
...
unfreed:<2>test1.c(11),512bytesat0x80519e4
{FEFEFEFEFEFEFEFEFEFEFEFE..............}
Memoryusagestatistics(global):
N)umberofallocationsmade:2
L)argestmemoryusage:1024
T)otalofallalloc()calls:1024
U)nfreedbytestotals:512
MEMWATCH为您显现真正招致成绩的行。假如您开释一个已开释过的指针,它会告知您。关于没有开释的内存也一样。日记开头部分显现统计信息,包含泄露了几内存,利用了几内存,和统共分派了几内存。
YAMD
YAMD软件包由NateEldredge编写,能够查找C和C++中静态的、与内存分派有关的成绩。在撰写本文时,YAMD的最新版本为0.32。请下载yamd-0.32.tar.gz(请参阅参考材料)。实行make命令来构建程序;然后实行makeinstall命令安装程序并设置工具。
一旦您下载了YAMD以后,请在test1.c上利用它。请删除#includememwatch.h并对makefile举行以下小小的修正:
利用YAMD的test1
gcc-gtest1.c-otest1
清单3展现了来自test1上的YAMD的输入。
清单3.利用YAMD的test1输入
YAMDversion0.32
Executable:/usr/src/test/yamd-0.32/test1
...
INFO:Normalallocationofthisblock
Address0x40025e00,size512
...
INFO:Normalallocationofthisblock
Address0x40028e00,size512
...
INFO:Normaldeallocationofthisblock
Address0x40025e00,size512
...
ERROR:MultiplefreeingAt
freeofpointeralreadyfreed
Address0x40025e00,size512
...
WARNING:Memoryleak
Address0x40028e00,size512
WARNING:Totalmemoryleaks:
1unfreedallocationstotaling512bytes
***FinishedatTue...10:07:152002
Allocatedagrandtotalof1024bytes2allocations
Averageof512bytesperallocation
Maxbytesallocatedatonetime:1024
24Kallocedinternally/12Kmappednow/8Kmax
Virtualprogramsizeis1416K
End.
YAMD显现我们已开释了内存,并且存在内存泄露。让我们在清单4中另外一个样本程序上尝尝YAMD。
清单4.内存代码(test2.c)
#include
#include
intmain(void)
{
char*ptr1;
char*ptr2;
char*chptr;
inti=1;
ptr1=malloc(512);
ptr2=malloc(512);
chptr=(char*)malloc(512);
for(i;i<=512;i++){
chptr=S;
}
ptr2=ptr1;
free(ptr2);
free(ptr1);
free(chptr);
}
您可使用上面的命令来启动YAMD:
./run-yamd/usr/src/test/test2/test2
清单5显现了在样本程序test2上利用YAMD失掉的输入。YAMD告知我们在for轮回中有“越界(out-of-bounds)”的情形。
清单5.利用YAMD的test2输入
Running/usr/src/test/test2/test2
Tempoutputto/tmp/yamd-out.1243
*********
./run-yamd:line101:1248Segmentationfault(coredumped)
YAMDversion0.32
Startingrun:/usr/src/test/test2/test2
Executable:/usr/src/test/test2/test2
Virtualprogramsizeis1380K
...
INFO:Normalallocationofthisblock
Address0x40025e00,size512
...
INFO:Normalallocationofthisblock
Address0x40028e00,size512
...
INFO:Normalallocationofthisblock
Address0x4002be00,size512
ERROR:Crash
...
Triedtowriteaddress0x4002c000
Seemstobepartofthisblock:
Address0x4002be00,size512
...
Addressinquestionisatoffset512(outofbounds)
Willdumpcoreaftercheckingheap.
Done.
MEMWATCH和YAMD都是很有效的调试工具,它们的利用办法有所分歧。关于MEMWATCH,您必要增加包括文件memwatch.h并翻开两个编译工夫标志。关于链接(link)语句,YAMD只必要-g选项。
ElectricFence
多半Linux分发版包括一个ElectricFence包,不外您也能够选择下载它。ElectricFence是一个由BrucePerens编写的malloc()调试库。它就在您分派内存后分派受回护的内存。假如存在fencepost毛病(凌驾数组开端运转),程序就会发生回护毛病,并当即停止。经由过程分离ElectricFence和gdb,您能够准确地跟踪到哪一行试图会见受回护内存。ElectricFence的另外一个功效就是可以检测内存泄露。
第2种情形:利用strace
strace命令是一种壮大的工具,它可以显现一切由用户空间程序收回的体系挪用。strace显现这些挪用的参数并前往标记情势的值。strace从内核吸收信息,并且不必要以任何特别的体例来构建内核。将跟踪信息发送到使用程序及内核开辟者都很有效。在清单6中,分区的一种格局有毛病,清单显现了strace的开首部分,内容是关于修改创立文件体系操纵(mkfs)的。strace断定哪一个挪用招致成绩呈现。
清单6.mkfs上strace的开首部分
execve("/sbin/mkfs.jfs",["mkfs.jfs","-f","/dev/test1"],&
...
open("/dev/test1",O_RDWR|O_LARGEFILE)=4
stat64("/dev/test1",{st_mode=&,st_rdev=makedev(63,255),...})=0
ioctl(4,0x40041271,0xbfffe128)=-1EINVAL(Invalidargument)
write(2,"mkfs.jfs:warning-cannotsetb"...,98mkfs.jfs:warning-
cannotsetblocksizeonblockdevice/dev/test1:Invalidargument)
=98
stat64("/dev/test1",{st_mode=&,st_rdev=makedev(63,255),...})=0
open("/dev/test1",O_RDONLY|O_LARGEFILE)=5
ioctl(5,0x80041272,0xbfffe124)=-1EINVAL(Invalidargument)
write(2,"mkfs.jfs:cantdeterminedevice"...,..._exit(1)
=?
清单6显现ioctl挪用招致用来格局化分区的mkfs程序失利。ioctlBLKGETSIZE64失利。(BLKGET-SIZE64在挪用ioctl的源代码中界说。)BLKGETSIZE64ioctl将被增加到Linux中一切的设备,而在这里,逻辑卷办理器还不撑持它。因而,假如BLKGETSIZE64ioctl挪用失利,mkfs代码将改成挪用较早的ioctl挪用;这使得mkfs合用于逻辑卷办理器。
第3种情形:利用gdb和Oops
您能够从命令利用用gdb程序(FreeSoftwareFoundation的调试器)来找堕落误,也能够从诸如DataDisplayDebugger(DDD)如许的几个图形工具之一利用gdb程序来找堕落误。您可使用gdb来调试用户空间程序或Linux内核。这一部分只会商从命令交运行gdb的情形。
利用gdbprogramname命令启动gdb。gdb将载进可实行程序标记并显现输出提醒符,让您能够入手下手利用调试器。您能够经由过程三种体例用gdb检察历程:
利用attach命令入手下手检察一个已运转的历程;attach将中断历程。
利用run命令实行程序并重新入手下手调试程序。
检察已有的中心文件来断定历程停止时的形态。要检察中心文件,请用上面的命令启动gdb。
gdbprogramnamecorefilename
要用中心文件举行调试,您不但必要程序的可实行文件和源文件,还必要中心文件自己。要用中心文件启动gdb,请利用-c选项:
gdb-ccoreprogramname
gdb显现哪行代码招致程序产生中心转储。
在运转程序或毗连到已运转的程序之前,请列出您以为有毛病的源代码,设置断点,然后入手下手调试程序。您可使用help命令检察周全的gdb在线匡助和具体的教程。
kgdb
kgdb程序(利用gdb的远程主机Linux内核调试器)供应了一种利用gdb调试Linux内核的机制。kgdb程序是内核的扩大,它让您可以在远程主机上运转gdb时毗连到运转用kgdb扩大的内核呆板。您能够接着深切到内核中、设置断点、反省数据并举行别的操纵(相似于您在使用程序上利用gdb的体例)。这个补钉的次要特性之一就是运转gdb的主机在引诱过程当中毗连到方针呆板(运转要被调试的内核)。这让您可以尽早入手下手调试。请注重,补钉为Linux内核增加了功效,以是gdb能够用来调试Linux内核。
利用kgdb必要两台呆板:一台是开辟呆板,另外一台是测试呆板。一条串行线(空调制解调器电缆)将经由过程呆板的串口毗连它们。您但愿调试的内核在测试呆板上运转;gdb在开辟呆板上运转。gdb利用串行线与您要调试的内核通讯。
请遵守上面的步骤来设置kgdb调试情况:
下载您的Linux内核版本合用的补钉。
将组件构建到内核,由于这是利用kgdb最复杂的办法。(请注重,有两种办法能够构建多半内核组件,好比作为模块或间接构建到内核中。举例来讲,日记记录文件体系(JournaledFileSystem,JFS)能够作为模块构建,或间接构建到内核中。经由过程利用gdb补钉,我们就能够将JFS间接构建到内核中。)
使用内核补钉偏重新构建内核。
创立一个名为.gdbinit的文件,并将其保留在内核源文件子目次中(换句话说就是/usr/src/linux)。文件.gdbinit中有上面四行代码:
setremotebaud115200
symbol-filevmlinux
targetremote/dev/ttyS0
setoutput-radix16
将append=gdb这一行增加到lilo,lilo是用来在引诱内核时选择利用哪一个内核的引诱载进程序。
image=/boot/bzImage-2.4.17
label=gdb2417
read-only
root=/dev/sda8
append="gdbgdbttyS=1gdb-baud=115200nmi_watchdog=0"
清单7是一个剧本示例,它将您在开辟呆板上构建的内核和模块引进测试呆板。您必要修正上面几项:
best@sfb:用户标识和呆板名。
/usr/src/linux-2.4.
12下一页
在这里你会学到更多的知识,学习linux,更要学习一种geek的精神,python之禅中也说过:以总结分享为荣,以跪求其解为耻;
linux教程之把握 Linux 调试手艺
如果你想在以后的生涯中在软件行业工作的话,学习linux是一项基本技能,所以打从你打算学习linux那天起,放弃windows吧!因为它除了能给你带来片刻的娱乐,别无其他;17:内核源代码树的目次。
bzImage-2.4.17:测试呆板大将引诱的内核名。
rcp和rsync:必需同意它在构建内核的呆板上运转。
清单7.引进测试呆板的内核和模块的剧本
set-x
rcpbest@sfb:/usr/src/linux-2.4.17/arch/i386/boot/bzImage/boot/bzImage-2.4.17
rcpbest@sfb:/usr/src/linux-2.4.17/System.map/boot/System.map-2.4.17
rm-rf/lib/modules/2.4.17
rsync-abest@sfb:/lib/modules/2.4.17/lib/modules
chown-Rroot/lib/modules/2.4.17
lilo
如今我们能够经由过程改成利用内核源代码树入手下手的目次来启动开辟呆板上的gdb程序了。在本示例中,内核源代码树位于/usr/src/linux-2.4.17。输出gdb启动程序。
假如统统一般,测试呆板将在启动过程当中中断。输出gdb命令cont以持续启动历程。一个罕见的成绩是,空调制解调器电缆大概会被毗连到毛病的串口。假如gdb不启动,将端口改成第二个串口,这会使gdb启动。
利用kgdb调试内核成绩
清单8列出了jfs_mount.c文件的源代码中被修正过的代码,我们在代码中创立了一个空指针非常,从而使代码在第109行发生段毛病。
清单8.修正事后的jfs_mount.c代码
intjfs_mount(structsuper_block*sb)
{
...
intptr;/*line1added*/
jFYI(1,("nMountJFSn"));
/*
*read/validatesuperblock
*(initializemountinodefromthesuperblock)
*/
if((rc=chkSuper(sb))){
gotoerrout20;
}
108ptr=0;/*line2added*/
109printk("%dn",*ptr);/*line3added*/
清单9在向文件体系收回mount命令以后显现一个gdb非常。kgdb供应了几条命令,如显现数据布局和变量值和显现体系中的一切义务处于甚么形态、它们驻留在那边、它们在哪些中央利用了CPU等等。清单9将显现回溯跟踪为该成绩供应的信息;where命令用来实行反跟踪,它将告知被实行的挪用在代码中的甚么中央中断。
清单9.gdb非常和反跟踪
mount-tjfs/dev/sdb/jfs
ProgramreceivedsignalSIGSEGV,Segmentationfault.
jfs_mount(sb=0xf78a3800)atjfs_mount.c:109
109printk("%dn",*ptr);
(gdb)where
#0jfs_mount(sb=0xf78a3800)atjfs_mount.c:109
#10xc01a0dbbinjfs_read_super...atsuper.c:280
#20xc0149ff5inget_sb_bdev...atsuper.c:620
#30xc014a89findo_kern_mount...atsuper.c:849
#40xc0160e66indo_add_mount...atnamespace.c:569
#50xc01610f4indo_mount...atnamespace.c:683
#60xc01611eainsys_mount...atnamespace.c:716
#70xc01074a7insystem_call()ataf_packet.c:1891
#80x0in??()
(gdb)
下一部分还将会商这个不异的JFS段毛病成绩,但不设置调试器,假如您在非kgdb内核情况中实行清单8中的代码,那末它利用内核大概天生的Oops动静。
Oops剖析
Oops(也称panic,张皇)动静包括体系毛病的细节,如CPU存放器的内容。在Linux中,调试体系溃散的传统办法是剖析在产生溃散时发送到体系把持台的Oops动静。一旦您把握了细节,就能够将动静发送到ksymoops有用程序,它将试图将代码转换为指令并将仓库值映照到内核标记。在良多情形下,这些信息就充足您断定毛病的大概缘故原由是甚么了。请注重,Oops动静其实不包含中心文件。
让我们假定体系方才创立了一条Oops动静。作为编写代码的人,您但愿办理成绩并断定甚么招致了Oops动静的发生,大概您但愿向显现了Oops动静的代码的开辟者供应有关您的成绩的年夜部分信息,从而实时地办理成绩。Oops动静是等式的一部分,但假如欠亨过ksymoops程序运转它也于事无补。上面的图显现了格局化Oops动静的历程</P></p>上一页12
如果你让他去用linux搭建一个web服务器,做一个linux网关,他就什么都不会了.他们把时间都浪费在了版本的转换上了. 通过一条缓慢的调制解调器线路,它也能操纵几千公里以外的远程系统。 另外Linux上也有很多的应用软件,安装运行了这些软件后,你就可以在Linux上编辑文档、图?片,玩游戏、上网、播放多媒体文件等。 我是学习嵌入式方向的,这学期就选修了这门专业任选课。 Linux高手更具有鼓励新手的文化精神。如何在Linux社区获得帮助,需要说明的是你要有周全的思考,准备好你的问题,不要草率的发问。 Linux的成功就在于用最少的资源最短的时间实现了所有功能,这也是符合人类进化的,相信以后节能问题会日益突出。 眼看这个学期的Linux课程已经告一段落了,我觉得有必要写一遍心得体会来总结一下这学期对着门课程的学习。 其中不乏很多IT精英的心血。我们学透以后更可以做成自己的OS!? 编程学习及开发,Linux是免费,开源的操作系统,并且可开发工具相当多,如果您支持自由软件,一定要同广大热爱自由软件人士一同为其不懈努力。
页:
[1]