




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、嵌入式linux应用程序调试方法一 前言2二 嵌入式linux的NFS开发环境的建立7三 GDB调试应用程序14四 内存工具174.1 MEMWATCH174.2 YAMD224.3 Electric Fence24五 C/C+代码覆盖、性能profiling工具245.1 用gcov来测试代码覆盖率255.2 使用gprof来优化你的C/C+程序35文件名 嵌入式linux应用程序调试方法适 用创 建作 者飞越丛林时间2007-08-08版本号V0.1说 明: 参考网络上的资料对nfs;gdb+gdbserver;gcov, gprof进行了一些描述;有不少资料是直接拷贝过来的,只相当于尝试
2、汇总一下吧J;实际上还处于毛胚阶段。修 改作 者时间版本号 感觉偶们项目组的调试手段很匮乏,刀耕火种也许有点过分,但是也差不多;当然这和偶这个小组长的能力有关,自己先汗一个。不过没有办法,整天要浸泡在对流程从头到尾的探索,修改,再探索,再修改;经验一点一点艰难的积累.顾此失彼,没有更多的时间来思考更多的手段问题,算是一个接口吧。痛定思痛,还是想办法提高一点生产力。在公司内没有找到相关的资料,于是这段时间就从网络这个巨人那里讨教窃取了一些资料,结合自己的项目step by step,“生产工具能够促进生产力的发展”,工具还是给调试带来了很多便利;因为记性不好,随手将一些资料连同自己的使用情况记录
3、了下来,共享出来希望对大家能够有所帮助。由于缺乏操作系统移植经验,很多东西没有系统知识的支持,在目标板上只能浅尝辄止,没有更深入的探讨,东西比较浅显,光脚不怕穿鞋的,抛砖引玉,希望更多的人能够将自己的使用经验分享出来,将linux的共享精神发扬光大J。当然也方便我们根据你的经验“拿来主义”。一 前言在嵌入式软件开发过程中,一般来说,花在测试和花在编码的时间比为3:1(实际上可能更多)。这个比例随着你的编程和测试水平的提高而不断下降,但不论怎样,软件测试对一般人来讲很重要。很多年前,一位开发人员为了对嵌入式有更深层次的理解,向Oracle询问了这样的一个问题:我怎么才能知道并懂得我的系统到底在干
4、些什么呢?Oracle面对这个问题有些吃惊,因为在当时没有人这么问过,而同时代的嵌入式开发人员问的最多的大都围绕“我怎么才能使程序跑的更快”、“什么编译器最好”等肤浅的问题。所以,面对这个不同寻常却异乎成熟的问题,Oracle感到欣喜并认真回复了他:你的问题很有深度很成熟,因为只有不断地去深入理解才有可能不断地提高水平。并且Oracle为了鼓励这位执着的程序员,把条关于嵌入式软件开发测试的秘诀告诉了他:1.懂得使用工具2.尽早发现内存问题3.深入理解代码优化4.不要让自己大海捞针5.重现并隔离问题6.以退为进7.确定测试的完整性8.提高代码质量意味着节省时间9.发现它,分析它,解决它10.利用
5、初学者的思维 这十条秘诀在业界广为流传,使很多人受益。本文围绕这十条秘诀展开论述。 .懂得使用工具通常嵌入式系统对可靠性的要求比较高。嵌入式系统安全性的失效可能会导致灾难性的后果,即使是非安全性系统,由于大批量生产也会导致严重的经济损失。这就要求对嵌入式系统,包括嵌入式软件进行严格的测试、确认和验证。随着越来越多的领域使用软件和微处理器控制各种嵌入式设备,对门益复杂的嵌入式软件进行快速有效的测试愈加显得重要。就象修车需要工具一样,好的程序员应该能够熟练运用各种软件工具。不同的工具,有不同的使用范围,有不同的功能。使用这些工具,你可以看到你的系统在干些什么,它又占用什么资源,它到底和哪些外界的东
6、西打交道。让你郁闷好几天的问题可能通过某个工具就能轻松搞定,可惜你就是不知道。那么为什么那么多的人总是在折腾个半死之后才想到要用测试工具呢?原因很多,主要有两个。一个是害怕,另一个是惰性。害怕是因为加入测试用具或测试模块到代码需要技巧同时有可能引入新的错误,所以他们总喜欢寄希望于通过不断地修改重编译代码来消除bug,结果却无济于事。懒惰是因为他们习惯了使用printf之类的简单测试手段。下面来介绍一些嵌入式常用的测试工具。.源码级调试器Source-level Debugger这种调试器一般提供单步或多步调试、断点设置、内存检测、变量查看等功能,是嵌入式调试最根本有效的调试方法。比如VxWor
7、ks TornadoII提供的gdb就属于这一种。.简单实用的打印显示工具printfprintf或其它类似的打印显示工具估计是最灵活最简单的调试工具。打印代码执行过程中的各种变量可以让你知道代码执行的情况。但是,printf对正常的代码执行干扰比较大(一般printf占用CPU比较长的时间),需要慎重使用,最好设置打印开关来控制打印。.ICE或JTAG调试器In-circuit EmulatorICE是用来仿真CPU核心的设备,它可以在不干扰运算器的正常运行情况下,实时的检测CPU的内部工作情况。像桌面调试软件所提供的:复杂的条件断点、先进的实时跟踪、性能分析和端口分析这些功能,它也都能提供
8、。ICE一般都有一个比较特殊的CPU,称为外合(bond-out)CPU。这是一种被打开了封装的CPU,并且通过特殊的连接,可以访问到CPU的内部信号,而这些信号,在CPU被封装时,是没法“看到”的。当和工作站上强大的调试软件联合使用时,ICE就能提供你所能找到的最全面的调试功能。但ICE同样有一些缺点:昂贵;不能全速工作;同样,并不是所有的CPU都可以作为外合CPU的,从另一个角度说,这些外合CPU也不大可能及时的被新出的CPU所更换。JTAG(Joint Test Action Group)虽然它最初开发出来是为了监测IC和电路连接,但是这种串行接口扩展了用途,包括对调试的支持。AD公司为
9、Blackfin设计的Visual Dsp+就支持高速的JTAG调试。.ROM监视器ROM Monitor ROM监控器是一小程序,驻留在嵌入系统ROM中,通过串行的或网络的连接和运行在工作站上的调试软件通信。这是一种便宜的方式,当然也是最低端的技术。它除了要求一个通信端口和少量的内存空间外,不需要其它任何专门的硬件。并提供了如下功能:下载代码、运行控制、断点、单步步进、以及观察、修改寄存器和内存。因为ROM监控器是操作软件的一部分,只有当你的应用程序运行时,它才会工作。如果你想检查CPU和应用程序的状态,你就必须停下应用程序,再次进入ROM监控器。.Data监视器Data Monitor这种
10、监视器在不停止CPU运行的情况下不仅可以显示指定变量内容,还可以收集并以图形形式显示各个变量的变化过程。.OS监视器Operating System Monitor操作系统监视器可以显示诸如任务切换、信号量收发、中断等事件。一方面,这些监视器能够为你呈现事件之间的关系和时间联系;另一方面,还可以提供对信号量优先级反转、死锁和中断延时等问题的诊断。.性能分析工具Profiler可以用来测试CPU到底耗在那里。profiler工具可以让你知道系统的瓶颈在那里、CPU的使用率以及需要优化的地方。.内存测试工具Memory Teseter可以找到内存使用的问题所在,比如内存泄露、内存碎片、内存崩溃等问
11、题。如果发现系统出现一些不可预知的或间歇性的问题,就应该使用内存测试工具测测看。.运行跟踪器Execution Tracer可以显示CPU执行了哪些函数、谁在调用、参数是什么、何时调用等情况。这种工具主要用于测试代码逻辑,可以在大量的事件中发现异常的那些。.覆盖工具Coverage Tester主要显示CPU具体执行了那些代码,并让你知道那些代码分支没有被执行到。这样有助于提高代码质量并消除无用代码。.GUI测试工具GUI Tester很多嵌入式应用带有某种形式的图形用户界面进行交互,有些系统性能测试足根掘用户输入响应时间进行的。GUI测试工具可以作为脚本工具有开发环境中运行测试用例,其功能包
12、括对操作的记录和回放、抓取屏幕显示供以后分析和比较、设置和管理测试过程(Rational公司的robot和Mercury的Loadrunner工具是杰出的代表)。很多嵌入式设备没有GUI,但常常可以对嵌入式设备进行插装来运行GUI测试脚本,虽然这种方式可能要求对被测代码进行更改,但是节省了功能测试和回归测试的时间。.自制工具Home-made tester在嵌入式应用中,有时候为了特定的目的,需要自行编写一些工具来达到某种测试目的。本人曾经编写的视频流录显工具在测试视频会议数据流向和变化上帮了大忙,帮公司找到了几个隐藏很深的bug。 .尽早发现内存问题 内存问题危害很大,不容易排查,主要有三种
13、类型:内存泄露、内存碎片和内存崩溃。对于内存问题态度必须要明确,那就是早发现早“治疗”。在软件设计中,内存泄露的“名气”最大,主要由于不断分配的内存无法及时地被释放,久而久之,系统的内存耗尽。即使细心的编程老手有时后也会遭遇内存泄露问题。有测试过内存泄露的朋友估计都有深刻地体验,那就是内存泄露问题一般隐藏很深,很难通过代码阅读来发现。有些内存泄露甚至可能出现在库当中。有可能这本身是库中的bug,也有可能是因为程序员没有正确理解它们的接口说明文档造成错用。在很多时候,大多数的内存泄露问题无法探测,但可能表现为随机的故障。程序员们往往会把这种现象怪罪于硬件问题。如果用户对系统稳定性不是很高,那么重
14、启系统问题也不大;但,如果用户对系统稳定很高,那么这种故障就有可能使用户对产品失去信心,同时也意味着你的项目是个失败的项目。由于内存泄露危害巨大,现在已经有许多工具来解决这个问题。这些工具通过查找没有引用或重复使用的代码块、垃圾内存收集、库跟踪等技术来发现内存泄露的问题。每个工具都有利有弊,不过总的来说,用要比不用好。总之,负责的开发人员应该去测试内存泄露的问题,做到防患于未然。内存碎片比内存泄露隐藏还要深。随着内存的不断分配并释放,大块内存不断分解为小块内存,从而形成碎片,久而久之,当需要申请大块内存是,有可能就会失败。如果系统内存够大,那么坚持的时间会长一些,但最终还是逃不出分配失败的厄运
15、。在使用动态分配的系统中,内存碎片经常发生。目前,解决这个问题最效的方法就是使用工具通过显示系统中内存的使用情况来发现谁是导致内存碎片的罪魁祸首,然后改进相应的部分。由于动态内存管理的种种问题,在嵌入式应用中,很多公司干脆就禁用malloc/free的以绝后患。内存崩溃是内存使用最严重的结果,主要原因有数组访问越界、写已经释放的内存、指针计算错误、访问堆栈地址越界等等。这种内存崩溃造成系统故障是随机的,而且很难查找,目前提供用于排查的工具也很少。总之,如果要使用内存管理单元的话,必须要小心,并严格遵守它们的使用规则,比如谁分配谁释放。 .深入理解代码优化讲到系统稳定性,人们更多地会想到实时性和
16、速度,因为代码效率对嵌入式系统来说太重要了。知道怎么优化代码是每个嵌入式软件开发人员必须具备的技能。就象女孩子减肥一样,起码知道她哪个地方最需要减,才能去购买减肥药或器材来减掉它。可见,代码优化的前提是找到真正需要优化的地方,然后对症下药,优化相应部分的代码。前面提到的profile(性能分析工具,一些功能齐全IDE都提供这种内置的工具)能够记录各种情况比如各个任务的CPU占用率、各个任务的优先级是否分配妥当、某个数据被拷贝了多少次、访问磁盘多少次、是否调用了网络收发的程序、测试代码是否已经关闭等等。但是,profile工具在分析实时系统性能方面还是有不够的地方。一方面,人们使用profile
17、工具往往是在系统出现问题即CPU耗尽之后,而profile工具本身对CPU占用较大,所以profile对这种情况很可能不起作用。根据Heisenberg效应,任何测试手段或多或少都会改变系统运行,这个对profiler同样适用!总之,提高运行效率的前提是你必须要知道CPU到底干了些什么干的怎么样。 .不要让自己大海捞针大海捞针只是对调试的一种生动比喻。经常听到组里有人对自己正在调试的代码说shit!可以理解,因为代码不是他写的,他有足够的理由去shit bug百出的代码,只要他自己不要写出这种代码,否则有一天同组的其它人可能同样会shit他写的代码。为何会有大海捞针呢?肯定是有人把针掉到海里咯
18、;那针为何会掉在海里呢?肯定是有人不小心或草率呗。所以当你在抱怨针那么难找的时候,你是否想过是你自己草率地丢掉的。同样,当你调试个半死的时候,你是否想过你要好好反省一下当初为了寻求捷径可能没有严格地遵守好的编码设计规范、没有检测一些假设条件或算法的正确性、没有将一些可能存在问题的代码打上记号呢?关于如何写高质量请参考林锐的高质量c+/c编程指南或关于C的0x8本“经书”。如果你确实已经把针掉在海里是,为了防止在找到之前刺到自己,你必须要做一些防范工作,比如戴上安全手套。同样,为了尽能地暴露和捕捉问题根源,我们可以设计比较全面的错误跟踪代码。怎么来做呢?尽可能对每个函数调用失败作出处理,尽可能检
19、测每个参数输入输出的有效性包括指针以及检测是否过多或过少地调用某个过程。错误跟踪能够让你知道你大概把针掉在哪个位置。 .重现并隔离问题如果你不是把针掉在大海了,而是掉在草堆里,那要好办写。因为至少我们可以把草堆分成很多块,一块一块的找。对于模块独立的大型项目,使用隔离方法往往是对付那些隐藏极深bug的最后方法。如果问题的出现是间歇性的,我们有必要设法去重现它并记录使其重现的整个过程以备在下一次可以利用这些条件去重现问题。如果你确信可以使用记录的那些条件去重现问题,那么我们就可以着手去隔离问题。怎么隔离呢?我们可以用#ifdef把一些可能和问题无关的代码关闭,把系统最小化到仍能够重现问题的地步。
20、如果还是无法定位问题所在,那么有必要打开“工具箱”了。可以试着用ICE或数据监视器去查看某个可疑变量的变化;可以使用跟踪工具获得函数调用的情况包括参数的传递;检查内存是否崩溃以及堆栈溢出的问题。 .以退为进猎人为了不使自己在森林里迷路,他常常会在树木上流下一些标记,以备自己将来有一天迷路时可以根据这些标记找到出路。对过去代码的修改进行跟踪记录对将来出现问题之后的调试很有帮助。假如有一天,你最近一次修改的程序跑了很久之后忽然死掉了,那么你这时的第一反映就是我到底改动了些什么呢,因为上次修改之前是好的。那么如何检测这次相对于上次的修改呢?没错,代码控制系统SCS或称版本控制系统VCS(Concur
21、rent Version Control,CVS是VCS的演化版本)。将上个版本check in下来后和当前测试版本比较。比较的工具可以是SCS/VCS/CVS自带的diff工具或其它功能更强的比较工具,比如BeyondCompare和ExamDiff。通过比较,记录所有改动的代码,分析所有可能导致问题的可疑代码。 .确定测试的完整性你怎么知道你的测试有多全面呢?覆盖测试(coverage testing)可以回答这个问题。覆盖测试工具可以告诉你CPU到底执行了那些代码。好的覆盖工具通常可以告诉你大概20%到40%代码没有问题,而其余的可能存在bug。覆盖工具有不同的测试级别,用户可以根据自己
22、的需要选择某个级别。即使你很确信你的单元测试已经很全面并且没有dead code,覆盖工具还是可以为你指出一些潜在的问题,看下面的代码:if (i = 0 & (almostAlwaysZero = 0 | (last = i)如果almostAlwaysZero为非,那么last=i赋值语句就被跳过,这可能不是你所期望的。这种问题通过覆盖工具的条件测试功能可以轻松的被发现。总之,覆盖测试对于提高代码质量很有帮助。 .提高代码质量意味着节省时间有研究表明软件开发的时间超过80%被用在下面几个方面:.调试自己的代码(单元测试).调试自己和其他相关的代码(模块间测试).调试整个系统(系统测试)更糟
23、糕的是你可能需要花费10-200倍的时间来找一个bug,而这个bug在开始的时候可能很容易就能找到。一个小bug可能让你付出巨大的代价,即使这个bug对整个系统的性能没有太大的影响,但很可能会影响让那些你可以看得到的部分。所以我们必须要养成良好的编码和测试手段以求更高的代码质量,以便缩短调试的代码。 .发现它,分析它,解决它这世界没有万能的膏药。profile再强大也有力不从心的时候;内存监视器再好,也有无法发现的时候;覆盖工具再好用,也有不能覆盖的地方。一些隐藏很深的问题即使用尽所有工具也有可能无法查到其根源,这时我们能做的就是通过这些问题所表现出来的外在现象或一些数据输出来发现其中的规律或
24、异常。一旦发现任何异常,一定要深入地理解并回溯其根源,直到解决为止。 .利用初学者的思维有人这样说过:“有些事情在初学者的脑子里可能有各种各样的情况,可在专家的头脑里可能就很单一”。有时候,有些简单的问题会被想的很复杂,有些简单的系统别设计的很复杂,就是由于你的“专家思维”。当你被问题难住时,关掉电脑,出去走走,把你的问题和你的朋友甚至你的小狗说说,或许他们可以给你意想不到的启发。 总结:嵌入式调试也是一门艺术。就想其它的艺术一样,如果你想取得成功,你必须具备智慧、经验并懂得使用工具。只要我们能够很好地领悟Oracle这十条秘诀,我相信我们在嵌入式测试方面就能够取得成功。武功秘籍排行榜:1.
25、The C programming language程序设计语言2. Pointers on C和指针3. C traps and pitfalls陷阱与缺陷4. Expert C Lanuage专家编程5. Writing Clean Code-Microsoft Techiniques for Developing Bug-free C Programs编程精粹-Microsoft 编写优质无错程序秘诀6. Programming Embedded Systems in C and C+嵌入式系统编程7.C语言嵌入式系统编程修炼8.高质量C+/C编程指南林锐9 C语言解惑二 嵌入式linu
26、x的NFS开发环境的建立在两台linux pc之间共享资源通常我们采用NFS技术;而在linux和windows之间共享资源,通常我们采用samba技术。NFS可以让你的PC通过网络将远端的NFS 服务器共享出来的文件mount到自己的系统中,在客户端看来使用NFS的远端文件就象是在使用本地文件一样。 使用NFS可以使应用程序的开发变得十分方便, 客户端不需要大容量的存储器,更不需要进行映像文件的烧录和下载,只要mount到服务器端的特定目录下,然后运行该目录下的程序即可观察到结果。建立NFS开发环境的工作分为两个方面,配置NFS服务器和配置客户端。 在开始前需要特别说明的一点:这里的描述是针
27、对自己使用情况的简单记录,可能你在使用过程中会存在一些问题,关于更多关于nfs和使用过程中的问题,建议参考这个网站上的资料和FAQ。在应用程序开发环节,NFS方式比ftp方式的执行效率要高,因为它不需要将linux server端的程序下载到嵌入式目标系统就可以调试。下面先将NFS建立的详细过程写一下,然后举一个简单的应用程序开发实例来比较ftp方式和nfs方式的不同。1 建立NFS开发环境 嵌入式linux的NFS开发环境包含着两个方面:一是linux server端的NFS Server支持;二是target board的NFS Client支持。1.1 linux server端1.1.
28、1 以root的身份登录,编译共享目录的配置文件exports,指定共享目录及其权限。vi /etc/exports在该文件中添加:/home/lqm(共享目录) 192.168.1.*(rw,sync,no_root_squash)添加的内容表示允许IP范围在192.168.1.*的计算机以读写的权限来访问共享目录/home/lqm。【注:】参数说明如下:rw读/写权限。如果设定只读权限,则设为ro。但是一般情况下,为了方便交互,要设置为rw。sync数据同步写入内存和硬盘。no_root_squash此参数用来要求服务器允许远程系统以它自己的root特权存取该目录。就是说,如果用户是roo
29、t,那么他就对这个共享目录有root的权限。很明显,该参数授予了target board很大的权利。安全性是首先要考虑的,可以采取一定的保护机制,在下面会讲一下保护机制。如果使用默认的root_squash,target board自己的根文件系统可能有很多无法写入,所以运行会受到极大的限制。在安全性有所保障的前提下,推荐使用no_root_squash参数。ro: 只读的权限,系统默认选项;如果不明确指定rw, 系统默然采用这种方式;root_squash: 在登入 NFS 主机使用分享之目录的使用者如果是 root 时,那么这个使用者的权限将被压缩成为匿名使用者,通常他的 UID 与 GI
30、D 都会变成 nobody 那个身份;如果不明确指定no_root_squas, 系统默然采用这种方式;all_squash: 不论登入 NFS 的使用者身份为何,他的身份都会被压缩成为匿名使用者,通常也就是 nobody 啦!anonuid: 前面关于 *_squash 提到的匿名使用者的 UID 设定值,通常为 nobody,但是你可以自行设定这个 UID 的值!当然,这个 UID 必需要存在于你的 /etc/passwd 当中!anongid: 同 anonuid ,但是变成 group ID 就是了;async: 资料会先暂存于内存当中,而非直接写入硬盘;1.1.2 起用保护机制可以通
31、过设定/etc/hosts.deny和/etc/hosts.allow文件来限制网络服务的存取权限。*/etc/hosts.deny*portmap:ALLlockd:ALLmountd:ALLrquotad:ALLstatd:ALL*/etc/hosts.allow*portmap:00lockd:00mountd:00rquotad:00statd:00同时使用这两个文件就会使得只有ip为00的机器使用NFS服务。你的target board的ip地址设定为1
32、00,这样就可以了。1.1.3 启动首先确认在/etc/rc.d/init.d 目录中是否有 portmap, nfs这两个可执行文件,如果没有你需要安装这两个程序,具体方法参见其它资料,不在这里描绘。首先要启动portmapper(端口映射)服务,这是NFS本身需要的。/etc/init.d/portmap start然后启动NFS Server。此时NFS会激活守护进程,然后开始监听客户端的请求。/etc/init.d/nfs startNFS Server启动后,还要检查一下linux server的iptables等,确定没有屏蔽NFS使用的端口和允许通信的主机。可
33、以首先在linux server上面进行NFS的回环测设。修改/etc/hosts.allow,把ip改为linux server的ip地址,然后在linux server上执行命令:mount -t nfs :/home/lqm /mntls /mnt如果NFS Server正常工作,应该在/mnt下面看到共享目录/home/lqm的内容。注:在启动了NFS之后又修改了/etc/exports,是不是还要重新启动nfs呢?这个时候我们就可以用exportfs命令来使改动立刻生效,该命令格式如下: exportfs -aruv -a :全部mount或者unmount /etc/exports
34、中的内容 -r :重新mount /etc/exports中分享出来的目录 -u :umount 目录 -v :在 export 的时候,将详细的信息输出到屏幕上。 具体例子: exportfs rv这个命令行要求全部重新输出一次。 在每次修改了/etc/exports文件后都要运行一次该命令。找不到这个命令,通常在/usr/sbin/ 目录中,如果没有在,利用locate或者其他搜索命令找找看(具体可以参见鸟哥的linux私房菜 基础篇, 为了以后使用方便还是将export PATH=/usr/sbin$PATH 这一行加入到自己目录的.bashrc文件中,然后重新“su 用户名”登陆一次
35、)。 1.2 target board端的client1.2.1 嵌入式linux内核应该支持NFS客户端。配置内核 进入File Systems -选项选中:NFS file system supportProvide NFSv3 client support 配置用户选项(这个按照罗威的说法应该是在编译busybox时设定,具体选项可能和实现有关) 进入Network Applications - 选项选中:portmap进入BusyBox -选项选中:mountmount:support NFS mounts完成以上配置后,即可编译产生映像文件。1.2.2 在target board的l
36、inux shell下,执行下列命令来进行NFS共享目录的挂载。mkdir /mnt/nfsmount -o nolock -t nfs :/home/lqm /mnt/nfsls /mnt/nfs由于很多嵌入式设备的根文件系统中不带portmap,所以一般都使用-o nolock参数,即不使用NFS文件锁,这样就可以避免使用portmap。如果顺利,在/mnt/nfs下,就可以看到linux server的共享文件夹下的内容了,而且两个文件夹内的修改是同步的。这里需要特别说明:我在RT-VS4104D上实际上是没有调通NFS,我估计是目标板操作系统本身的问题,具体原因不明,因为对操作系统制作
37、不是很清楚,操作系统人员又忙,所以不得已放弃。但是我在自己电脑山NFS输出的目录,通过上面的操作步骤在30和88上都很容易mount成功,所以应该不是服务器端设置的问题。大家有机会还是最好把这个东西给走通,因为在调试阶段,采用这种方式的确非常方便。1.3 其他说明1.3.1设置的实例: a). /tmp *(rw,no_root_squash) /*号表示所有的IP都可以访问 b). /tmp *(rw) /home/public 192.168.0.*(rw) *(ro) /下面两行作用一样 /home/public /24(
38、rw) *(ro) c). /home/test 00(rw) /只对某部机器设置权限 d). /home/linux *.(rw,all_squash,anonuid=40,anongid=40) /当*.登陆此NFS主机,并且在/home/linux下面写入档案时,该档案的所有人与所有组,就会变成/etc/passwd里面对应的UID为40的那个身份的使用者了. 1.3.2.权限问题假设/etc/exports里面的内容为 #vi /etc/exports /tmp *(rw,no_root_squash) /home/public
39、 192.168.0.*(rw) *(ro) /home/test 00(rw) /home/linux *.(rw,all_squash,anonuid=40,anongid=40) 假设我们在00这个client端登陆此NFS主机(),那么 情况一:在00的帐号为test这个身份,同时,NFS主机上也有test这个帐号 a).由于NFS主机的/tmp权限为-rwxrwxrwt,所以我(test在00上)在/tmp下面具有存取的权限,并且写入档案的所有人为test.
40、 b).在/home/public中,由于我有读写的权限,如果NFS主机在/home/public这个目录的权限对于test开放写入的话,那么就可以读写,并且写入档案的所有人是test。如果NFS主机的/home/public对于test这个使用者并没有开放写入权限时,那就无法写入,虽然/etc/exports里面是rw,也不起作用. c).在/home/test中,权限与/home/public有相同的状态,需要NFS主机的/home/test对于test有开放的权限. d).在/home/linux当中,不论是何种的user,身份都会被变成UID=40的这个帐号 情况二:如果我们在192.
41、168.0.100的身份为test2,但是NFS主机却没有test2这个帐号时 a).在/tmp下还是可以写入,但是写入的档案所有人变成nobody. b).在/home/public与/home/test里面是否可以写入,还需要看/home/public的权限而定,不过身份就被变成nobody了 c)/home/linux下的身份还是变成UID=40的帐号. 情况三:在00的身份为root a).在/tmp里面可以写入,但是由于no_root_squash的参数,改变了预设的root_squash的设定值,所以在/tmp写入档案的所有人为root了. b).在/home
42、/public底下的身份被压缩成了nobody,因为预设的属性都具有root_squash,所以档案所有人就变成了nobody. c)./home/test情况与/home/public相同. d)./home/linux中,root的身份也被压缩成UID=40的那个使用者了.1.3.3 服务器端几个有用的文件l /var/lib/nfs/xtab按照我的理解这个文件的内容和/etc/exports类似,只是这里将一些系统默认的选项补齐;一个实例如下:root-nfs# cat etab/home/zpf/ftp 172.16.51.*(rw,sync,wdelay,hide,secure,n
43、o_root_squash,no_all_squash,subtree_check,secure_locks,mapping=identity,anonuid=-2,anongid=-2)l /var/lib/nfs/rmtab按照我的理解,这个文件记录一段时间内系统nfs客户的列表,一个实例如下:root-nfs# cat rmtab50:/home/test:0x0000000450:/iFind/src/h323/src:0x0000000c50:/iFind_zh/iFind/src/h323/src:0x0000000
44、130:/home/test:0x0000000443:/home/zpf/rtvs4104d_zpf/filesystem/data:0x0000002044:/home/zpf/rtvs4104d_zpf/filesystem/data:0x0000000744:/home/zpf:0x0000000543:/home/zpf:0x0000001230:/home/zpf:0x0000000288:/home/zpf:0x00000005
45、88:/home/zpf/ftp:0x0000000188:/home/zpf/ftp/arm_linux_resource:0x00000001最后一项是我目前通过88挂载了目录/home/zpf/ftp/arm_linux_resource三列的含义分别为:客户端的ip:NFS服务器输出的目录:最后一项的数字的函数待差。l /var/lib/nfs/xtab按照我的理解,这个文件给出了当前系统还处于挂载状态的客户列表root-nfs# cat xtab/home/zpf/ftp 88(rw,sync,w
46、delay,hide,secure,no_root_squash,no_all_squash,subtree_check,secure_locks,mapping=identity,anonuid=-2,anongid=-2)目前88通过nfs挂载了共享目录。l /proc/fs/nfs/exportsroot-nfs# cat exports# Version 1.1# Path Client(Flags) # IPs/home/zpf/ftp 88(rw,no_root_squash,sync,wdelay) # 88我理解
47、的含义:NFS服务器输出的目录 客户端(挂载时的flag)#当前挂载的设备IP地址组需要说明的一点:在这四个文件中,只有/var/lib/nfs/rmtab 给出的目录是客户端实际挂载的目录(共享/home/zpf/ftp, 客户端可以挂载它的一个子目录/home/zpf/ftp/arm_linux_resource),其他给出的都是服务器共享的目录名称。2 应用程序实例编写一个简单的C程序test.c-/*This is a test program.*/int main(void)int i;for(i=0;i10;i+) printf(Hello World %d times.n,i);
48、return 0;-编译该程序:arm-linux-gcc -o test test.c2.1 FTP方式首先将test下载到target board。启动target board的linux,在超级终端中执行:cd /varftp ftpbin /以binary mode传输文件ftpget testftpexit然后修改文件属性:chmod +x test./test这时可以查看结果了。2.2 NFS方式在target board端挂载linux server的共享输出目录,并且运行程序。mkdir /mnt/nfsmount -o nolock -t nfs :/home/lqm /mn
49、t/nfsls /mnt/nfs这时应该可以显示linux server的共享目录的内容。然后执行:./test3 总结 这两种方式在应用程序不是特别复杂时区别不是很大,但是当开发程序比较复杂时,采用NFS方式显然效率要高得多。完成应用程序得开发,调试好后就可以下载到嵌入式目标板的flash文件系统,或者直接编译到嵌入式linux内核并且烧写到flash,从而最终成为一个独立的嵌入式应用程序。参考书目:building embedded linux systems 嵌入式linux系统开发详解基于EP93XX系列ARM这两本书在过程上都比较细致,很适合初学者学习。在实践熟悉的基础上,提升理论高
50、度,这是我所认可的学习方法。 三 GDB调试应用程序GNU工具链中的GDB可以读linux开发的应用程序进行调试,它能够控制程序的执行、查看和改变程序的变量、分析程序的内在结构、研究崩溃程序的核心文件等等;在嵌入式系统中,同样可以利用专用的gdb调试应用程序,由于通常目标板上的资源都比较有限,所以利用gdb在嵌入式系统上调试应用程序时,通常和nfs配合使用。在嵌入式目标系统应用程序的调试中,由于应用程序是在嵌入式目标系统上运行,而gdb调试器则运行在linux服务器上,因此需要采用远程调试的方法;采用这种远程调试的原因和交叉编译的原因是一样的,均由于受到嵌入式目标板系统设备上有限的资源限制,因
51、此需要利用linux服务器的部分资源,完成系统的调试任务。远程调试环境由运行在linux服务器上特殊版本的gdb调试器和运行载嵌入式目标机上的调试服务器gdbserver共同构成,两者通过串口或TCP连接。使用 GDB标准串行协议协同工作,实现对目标机上的系统内核和上层应用的监控和调试功能。就目前而言,嵌入式Linux系统中,主要有三种远程调试方法,分别适用于不同场合的调试工作:用ROM Monitor调试目标机程序、用KGDB调试系统内核和用gdbserver调试用户空间程序。这三种调试方法的区别主要在于:目标机远程调试stub 的存在形式的不同,而其设计思路和实现方法则是大致相同的。 而我
52、们最常用的是调试应用程序,就是采用gdb+gdbserver的方式进行调试。在很多情况下,用户需要对一个应用程序进行反复调试,特别是复杂的程序。采用GDB方法调试,由于嵌入式系统资源有限,一般不能直接在目标系统上进行调试,通常采用gdb+gdbserver的方式进行调试。Gdbserver在目标系统中运行,gdb则在linux服务器上运行。 一般linux发行版中都有一个可以运行的gdb,但开发人员不能直接使用该发行版中的gdb来做远程调试,而要获取gdb的源代码包,针对 arm平台作一个简单配置,重新编译得到相应gdb。gdb的源代码包可以从http: /.tw/L
53、inux/sourceware/gdb/releases/下载,最新版本为gdb-6.6。或者直接到GNU的网站上下载:/software/gdb/download/下载到某个目录,例如下载到目录:/home/vicky。下载完后,进入/home/vicky目录,配置编译步骤如下: #tar jxvf gdb-6.6-tar-bz2 #cd gdb-6.6 #./configure -target=arm-linux -prefix=/usr/local/arm-gdb -v #make #make install #export PATH=$PATH:/us
54、r/local/arm-gdb 进入gdbserver目录(在gdb-6.6/gdb/gdbserver, 找这个找了半天.):#./configure -target=arm-linux -host=arm-linux #make CC=/usr/local/arm/3.4.1/bin/arm-linux-gcc (这一步要指定arm-linux-gcc的位置,具体的问题根据自己系统中的设置修改这个命令行) 通过nfs或者下载将gdb放到目标板,根据资料,需要调试的程序也可以采用nfs,也可以直接下载到目标板上。下面就可以用gdb+gdbserver调试我们开发板上的程序了。做如下假设:目标
55、机IP:43, linux服务器30; 要进行gdb调试,首先要在目标系统上启动gdbserver服务。在gdbserver所在目录下输入命令: 在串口中输入#./gdbserver 30:15000 runapp表示目标板上的gdbserver接收来自linux服务器30的调试指令,gdbserver监听15000 端口,然后启动runapp程序;(可能这个时候会提示找不到libthread_db.so.1这个动态库,到/usr/local/arm/3.4.1/arm-linux/lib 也就是你arm交叉编译环境中的库中找到这个文件,下载到设备上,并且保证这个库文件放置在LD_LIBRARY_PATH 指定的那些目录中,否则,你需要利用export LD_LIBRARY_PATH= 重新指定
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 中国节能生活锅炉行业市场发展前景及发展趋势与投资战略研究报告(2024-2030)
- 2024年中国交通铝行业发展调查报告
- 2025年 南昌大学校内外招聘考试笔试试题附答案
- 2025年 河北软件职业技术学院选聘工作人员考试试题附答案
- 桑蚕丝定位男长巾项目投资可行性研究分析报告(2024-2030版)
- 2025年 安康市审计局事业单位招聘考试笔试试题附答案
- 2023-2028年中国河南白酒行业市场深度分析及投资策略咨询报告
- 2025年中国智慧商城建设市场前景预测及投资规划研究报告
- 2025年中国屏山炒青茶行业市场发展监测及投资战略规划报告
- 宝鸡醋项目可行性研究报告
- 关键工程施工进度计划网络图及施工进度总体计划网络图
- SB/T 10784-2012洗染服务合约技术规范
- GB/T 16940-2012滚动轴承套筒型直线球轴承外形尺寸和公差
- GB/T 15814.1-1995烟花爆竹药剂成分定性测定
- 煤矿安全规程露天部分参考题库(含答案)
- 紫铜材质证明
- 新产品评审管理办法
- (参考)菲达公司国内电除尘器业绩表
- 大学生职业生涯规划与就业指导教案第5讲:兴趣探索
- 门店电表记录表
- 七年级劳技 花卉种植 花卉用途 PPT学习教案
评论
0/150
提交评论