打造嵌入式c调试系统1-什么是调试系统

本系列文章针对嵌入式环境下c语言应用而言的,对其他系统、语言的程序有一定的参考意义,毕竟调试思想应该是相通的。

什么是调试系统

调试(debug)没有标准的定义,个人的理解是,调试是一种能够快速定位乃至能预防问题发生的技术手段。调试针对的是已发生问题的定位,这一点问题不大,对于预防问题发生有些人可能不赞同,其实,程序能够正常运行,不代表程序没有问题(没有完美的软件),就像人,看起来活蹦乱跳的,但不代表身体很健康,也可能处于一种亚健康状态,只是暂时没表现出来而已,如果程序处于亚健康状态,找出其中的问题,这个工作也是调试的范畴。

调试就是debug,一说到debug,大家可能都想会想到DEBUG版本和gdb(或windows的vs,本文针对嵌入式的,对其他平台也有参考意义),但调试技术的范围比DEBUG版本和调试器要大,使用调试器(gdb)调试DEBUG版本的程序,当然是调试工作的一部分,但调试工作远不止这些,调试贯穿了整个开发运营过程,可以从以下几个阶段来认识调试:

  • 设计阶段,调试设计是调试的重要环节,出了问题,没有准备、没有手段,不可能快速定位到问题。
  • 开发阶段,开发时,软件工程师加班写bug是不可避免的,而掌握调试方法可以加快开发进度,减少加班时间。
  • 测试阶段,调试与测试本是兄弟,这个环节是互补的、相辅相成的。
  • 运营阶段,事中分析、事后分析是最能体现调试价值的活,时间就是金钱,这里就能很好体现出来。
    所以调试是一个体系,是一系列设计、方法、工具应用的组合,这就是所谓的调试系统。

调试系统的意义

成体系的实施调试过程,能大幅度的提高调试的成功率与效率。提高项目的成功率,调试过程中,能发现系统的问题与缺陷,有助于反向推动系统的发展水平,形成良性循环。

调试与测试

测试与调试都是与软件的问题打交道的,所有可以连起来用,如完成功能调测,为更好的学习调试,需要对测试与调试做一些区分,这里列举了一些调测的共同与差异。

共同点

  • 是软件质量保证的一部分,也是最重要的2个点。
  • 都是与软件bug打交道的,有些工作是重叠的。
  • 调试与测试都是需要经过设计的,都是成体系的东西。
  • 很多调测的技术是相通的,用的工具都有重叠。
  • 实施调测的可能是同一拨人,调测一家人。

差异点

  • 侧重点不一样,测试重在通过用例提高覆盖率,发现问题(挑错)与防止已出现问题的再次出现,而调试重在定位解决问题(排错)。
  • 测试一般要求可自动连续运行且中间较少要求人工参与,调试则无此要求。
  • 测试测试事前,是前质量保证手段,调试工作发生在事中或事后,是后质量保证手段。
  • 稳定性不同,测试的预见性较强,而调试需很多推理、猜测、验证的过程。
  • 度量方式不一样,测试度量的主要有覆盖率、自动化程度,调试一般就讲究效率(够快)和成功率(减少迷案)。
  • 项目中参与阶段不一样,测试一般在发布前完成,而调试是全阶段的。
  • 活动流程不一致,测试是有计划、章程的,调试是按需求来的。
  • 设计的重点不一样,测试重在可重复场景设计、如何获取输入输出、模拟等,调试重在过程监控,事故定位与现场还原。
  • 系统调优是调试工作经常要做的工作,测试关注的是优化的效果、极限验证的情况。

嵌入式调试特点

嵌入式平台与pc平台的差异决定了嵌入式调试与pc调试的差异,主要体现在资源限制方面:

  • 存储空间不一样,很多嵌入式系统对flash有限制,有好工具放不进去也白搭,工具选用有取舍,必要的情况下要裁剪、重复造简单的轮子。
  • 内存和cpu有限制,调试系统不能占用太多的系统资源,应用功能优先,调试需取舍。

需要明确一点,调试设计是需要消耗系统资源的,虽然说功能优先,但完全不给调试资源,调试活动就很难达成,这需要整体取舍,调试系统也可以反向优化资源的使用,一般情况下,在调试上的投入能抵消调试自身的消耗(资源和效率就是水,看你挤不挤得出来),linux的proc虚拟文件系统就是例子,资源再紧张,也不能把这个干掉。这就是磨刀不误砍柴工,在做调试设计之前,最好能定出最大资源占用比例,避免做的过程中缩手缩脚。

调试系统的组成

这里根据个人经验收集了一些调试系统包含的内容,并分别做一些说明。不同的调试点适用于不同的场合,重要性大家可以自己判别。具体的实现方式,后续的系列文章会做说明。

状态信息

参考linux的proc虚拟文件系统,有多少工具是基于proc系统的,linux嵌入式工程师都应该能体会到它的重要性,proc文件系统是一个典型的状态信息系统。光状态信息这一项都能成为一个系统,proc文件系统是非常复杂的,涉及面又太广,很少人说完全熟悉proc每项内容。
状态信息系统不光对内核有重大意义,也是应用不可或缺的一部分,所谓的状态信息系统,包括:

  • 状态信息是一些全局量、过程量、统计信息的外在体现。
  • 系统当前的运行状态,对监控者来说,系统是透明的,运行过程是可量化的。
  • 包含必要的统计信息,系统功能可能用不到这些信息,但对系统监控是不可缺少的。
  • 信息需成体系,如相关模块A与B,模块A的输出能与模块B的输入对接,对接的不止是功能,状态信息也能匹配。

日志信息

日志是调试系统的重要一环,linux的dmesg可以看作为一种日志,日志分为几类:

  • 动态日志,能够动态调整级别的,有需要就输出。
  • 静态日志,DEBUG模式的日志或者固定输出的日志。
  • 磁盘或flash日志、内存日志(带缓存的,dmesg是动态内存日志)、直接日志(不带缓存,直接输出)

资源管理

所谓资源包括内存、句柄、线程、锁、CPU占用、带宽等管理,包括:

  • 栈溢出保护、栈深度检测
  • 堆内存管理,包括使用量、泄露、double free等情况管理
  • 句柄管理,统计、误关闭处理、泄露等管理
  • 线程占用资源、线程数量管理
  • 锁统计与测试设计
    资源管理这块,程序内部没有相关的资源管理设计,通过外部工具也能做一部分,但设计了过后,会加快排查速度,提高结案率。

系统调优

调优也是一种调试工作,就是边调试边优化,调优是个细活,外部工具能把握大方向,细化还得靠内部统计信息,如老大要求内存减少20%,你得知道内存都用在那个地方了,单靠外部工具很难知道每个模块用了多少内存。

异常退出

简单说就是程序崩溃了,嵌入式设备上你不大可能能用上coredump信息,这个东西太大,一般还得自己捕获崩溃信息,定位出崩溃栈。当然,异常退出的原因非常多,需要根据退出时的信号来分析,如oom-killer也是一种典型的异常退出方式。

其他

  • 终端输出重定向、捕获、过滤分析等。
  • 工具编写(脚本、状态自动监测分析等)。

知识点

设计调试系统时,掌握一些知识和工具是非常必要的,下面是个人收集的一些通用的(不包括网络、磁盘等,自成领域)知识点。

  • elf格式、内存分布、bfd库、符号symbol获取、proc中maps(smaps、status等)理解。
  • 帧栈的理解,APCS、unwind栈回溯。
  • 信号signal种类与处理,Interrupted system call处理,ucontext函数族,线程锁,线程私有数据、nptl、内存屏障。
  • ptrace系统调用使用方法,进程操作(wait,waitpid等)。
  • fuse系统、netlink机制、共享内存、消息队列。
  • top,htop、strace,gdb、linux proc信息、gcc编译选项。
  • tcmalloc、jemalloc、libunwind等外部库。
  • 强弱符号、gcc wrap函数替换、动态库符号导入与覆盖。
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值