精华内容
下载资源
问答
  • Crash

    2016-02-15 12:16:18
    如何获得crash日志 如何解析crash日志 如何分析crash日志  1. iOS策略相关  2. 常见错误标识  3. 代码bug 一、如何获得crash日志 当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在

    原文地址:http://my.oschina.net/u/1418722/blog/349581

    Outline

    如何获得crash日志
    如何解析crash日志
    如何分析crash日志
         1. iOS策略相关
         2. 常见错误标识
         3. 代码bug


    一、如何获得crash日志

    当一个iOS应用程序崩溃时,系统会创建一份crash日志保存在设备上。这份crash日志记录着应用程序崩溃时的信息,通常包含着每个执行线程的栈调用信息(低内存闪退日志例外),对于开发人员定位问题很有帮助。

    如果设备就在身边,可以连接设备,打开Xcode - Window - Organizer,在左侧面板中选择Device Logs(可以选择具体设备的Device Logs或者Library下所有设备的Device Logs),然后根据时间排序查看设备上的crash日志。这是开发、测试阶段最经常采用的方式。

    如果应用程序已经提交到App Store发布,用户已经安装使用了,那么开发者可以通过iTunes Connect(Manage Your Applications - View Details - Crash Reports)获取用户的crash日志。不过这并不是100%有效的,而且大多数开发者并不依赖于此,因为这需要用户设备同意上传相关信息,详情可参见iOS: Providing Apple with diagnostics and usage information摘要。

    考虑到并不是所有iPhone用户都允许自动发送诊断报告(crash日志),而且对于部分提交到Apple得crash日志,开发者还需要手动去拉取,然后找到对应的符号文件进行解析——这是一件很繁琐的事情。所以实际项目开发中,通常接入现有的crash收集工具(参考1参考2),或者自己编写一个进行自动化收集、解析和统计汇总。


    二、如何解析crash日志

    当获得一份crash日志时,我们需要将初始展示的十六进制地址等原始信息映射为源代码级别的方法名称和代码行数,使其对开发人员可读。这个过程称为符号化解析。要成功地符号化解析一份crash日志,我们需要有对应的应用程序二进制文件以及符号(.dSYM)文件。

    如果处于开发调试阶段,通常Xcode都能匹配到crash日志对应的二进制文件和符号文件,所以能够帮我们自动解析。

    如果处于测试阶段,测试人员已经安装了不同的版本(比如alpha、beta版本),那么需要保存好对应版本的二进制文件和符号文件,以便在应用程序崩溃时对crash日志进行解析。对于这种场景下产生的crash日志,只需要将.crash文件、.app文件和.dSYM文件三者放在同一个目录下,然后将.crash文件拖放到Xcode - Window - Organizer中左侧面板Library下的Device Logs中,即可进行解析。

    如果要提交发布,那么我们通常会先执行Clean,再Build,最后通过Product - Archive来打包。这样,Xcode会将二进制文件和符号文件归档在一起,可以通过Organizer中的Archives进行浏览。

    这里是一份关于如何解析crash日志的讨论:http://stackoverflow.com/questions/1460892/symbolicating-iphone-app-crash-reports 。


    三、如何分析crash日志

    在分析一份crash日志之前,如果开发人员对于常见的错误类型有所了解,那定是极好的。
    crash日志的产生来源于两种问题:违反iOS策略被干掉,以及自身的代码bug。

    1. iOS策略

    1.1 低内存闪退
    前面提到大多数crash日志都包含着执行线程的栈调用信息,但是低内存闪退日志除外,这里就先看看低内存闪退日志是什么样的。
    我们使用Xcode 5和iOS 7的设备模拟一次低内存闪退,然后通过Organizer查看产生的crash日志,可以发现Process和Type都为Unknown:



    而具体的日志内容如下:



    第一部分是崩溃信息,包括识别标识、软硬件信息和时间信息等。
    第二部分是内存页分配信息,以及当前占用内存最多的进程,上图中为crashTypeDemo。
    第三部分是具体的进程列表,描述着每个进程使用内存的情况以及当前状态。在较早的版本中可以在某些进程后面看到“jettisoned”字样,表明这些进程使用过多内存被终止了,而现在我们看到的是“vm-pageshortage”字样。

    当iOS检测到内存过低时,它(的VM系统)会发出低内存警告通知,尝试回收一些内存;如果情况没有得到足够的改善,iOS会终止后台应用以回收更多内存;最后,如果内存还是不足,那么正在运行的应用可能会被终止掉。
    所以,我们的应用应该合理地响应系统抛出来的低内存警告通知,对一些缓存数据和可重新创建的对象进行释放,同时要避免出现内存泄露等问题。

    低内存闪退是由iOS策略决定终止应用程序运行的,同样基于iOS策略的还有Watchdog超时和用户强制退出。

    1.2 Watchdog超时
    Apple的iOS Developer Library网站上,QA1693文档中描述了Watchdog机制,包括生效场景和表现。如果我们的应用程序对一些特定的UI事件(比如启动、挂起、恢复、结束)响应不及时,Watchdog会把我们的应用程序干掉,并生成一份响应的crash报告。

    这份crash报告的有趣之处在于异常代码:“0x8badf00d”,即“ate bad food”。
    如果说特定的UI事件比较抽象,那么用代码来直接描述的话,对应的就是(创建一个工程时Xcode自动生成的)UIApplicationDelegate的几个方法:



    所以当遇到Watchdog日志时,可以检查下上图几个方法是否有比较重的阻塞UI的动作。

    QA1693举的例子是在主线程进行同步网络请求。如果我们是在公司的Wifi环境下使用则一切顺利,但当应用程序发布出去面向很大范围的用户,在各种网络环境下运行,则不可避免地会出现一片Watchdog超时报告。
    另一种可能出现问题的场景就是数据量比较大的情况下进行的数据库版本迁移(同样是在主线程上),这也是促使我写这篇总结的一个直接因素。

    1.3 用户强制退出

    一看到“用户强制退出”,首先可能想到的双击Home键,然后关闭应用程序。不过这种场景是不会产生crash日志的,因为双击Home键后,所有的应用程序都处于后台状态,而iOS随时都有可能关闭后台进程,所以这种场景没有crash日志。

    另一种场景是用户同时按住电源键和Home键,让iPhone重启。这种场景会产生日志(仅验证过一次),但并不针对特定应用程序。

    这里指的“用户强制退出”场景,是稍微比较复杂点的操作:先按住电源键,直到出现“滑动关机”的界面时,再按住Home键,这时候当前应用程序会被终止掉,并且产生一份相应事件的crash日志。



    通常,用户应该是遇到应用程序卡死,并且影响到了iOS响应,才会进行这样的操作——不过感觉这操作好高级,所以这样的crash日志应该比较少见。

    2. 常见错误标识

    2.1 Exception codes
    上面“用户强制退出”的crash日志中的Exception Codes是“0xdeadfa11”,再上面“Watchdog超时”的crash日志中的Exception Codes是“0x8badf00d”,这些都是特有的Exception codes。
    根据官方文档描述,至少有以下几种特定异常代码:

    0x8badf00d错误码:Watchdog超时,意为“ate bad food”。

    0xdeadfa11错误码:用户强制退出,意为“dead fall”。

    0xbaaaaaad错误码:用户按住Home键和音量键,获取当前内存状态,不代表崩溃。



    0xbad22222错误码:VoIP应用(因为太频繁?)被iOS干掉。

    0xc00010ff错误码:因为太烫了被干掉,意为“cool off”。

    0xdead10cc错误码:因为在后台时仍然占据系统资源(比如通讯录)被干掉,意为“dead lock”。

    2.2 Exception types
    查看我们的crash分析报告邮件,会发现最经常遇到的错误类型是SEGV(Segmentation Violation,段违例),表明内存操作不当,比如访问一个没有权限的内存地址。
    当我们收到SIGSEGV信号时,可以往以下几个方面考虑:
    访问无效内存地址,比如访问Zombie对象;
    尝试往只读区域写数据;
    解引用空指针;
    使用未初始化的指针;
    栈溢出;
    此外,还有其它常见信号:
    SIGABRT:收到Abort信号,可能自身调用abort()或者收到外部发送过来的信号;
    SIGBUS:总线错误。与SIGSEGV不同的是,SIGSEGV访问的是无效地址(比如虚存映射不到物理内存),而SIGBUS访问的是有效地址,但总线访问异常(比如地址对齐问题);
    SIGILL:尝试执行非法的指令,可能不被识别或者没有权限;
    SIGFPE:Floating Point Error,数学计算相关问题(可能不限于浮点计算),比如除零操作;
    SIGPIPE:管道另一端没有进程接手数据;

    3. 代码bug
    此外,比较常见的崩溃基本都源于代码bug,比如数组越界、插空、多线程安全性、访问野指针、发送未实现的selector等。如果引入Core Data,则又有另外一些常见问题,不过这是另一个话题了。
    展开全文
  • crash

    千次阅读 2012-12-31 15:09:49
    程序crash之后,使用 Crash 工具分析 Linux dump 文件 51099.com发布 来源:网络 发布时间:2010-11-23 字体: [大 中 小]  关键字:分析 文件 工具 之后 使用 程序 内核 内存 系统 一个     ...
    程序crash之后,使用 Crash 工具分析 Linux dump 文件 51099.com发布 来源:网络 发布时间:2010-11-23 字体: [ ]  
       关键字:分析 文件 工具 之后 使用 程序 内核 内存 系统 一个
     
     

    前言

    Linux 内核(以下简称内核)是一个不与特定进程相关的功能集合,内核的代码很难轻易的在调试器中执行和跟踪。开发者认为,内核如果发生了错误,就不应该继续运行。因此内核发生错误时,它的行为通常被设定为系统崩溃,机器重启。基于动态存储器的电气特性,机器重启后,上次错误发生时的现场会遭到破坏,这使得查找内核的错误变得异常困难。

    内核社区和一些商业公司为此开发了很多种调试技术和工具,希望可以让内核的调试变得简单。其中一种是单步跟踪调试方法,即使用代码调试器,一步步的跟踪执行的代码,通过查看变量和寄存器的值来分析错误发生的原因。这一类的调试器有 gdb,kdb, kgdb。另一种方法是在系统崩溃时,将内存保存起来,供事后进行分析。多数情况下,单步调式跟踪可以满足需求,但是单步跟踪调试也有缺点。如遇到如下几种情况时:

    • 错误发生在客户的机器上。
    • 错误发生在很关键的生产机器上。
    • 错误很难重现。

    单步调试跟踪方法将无能为力。对于这几种情况,在内核发生错误并崩溃的时候,将内存转储起来供事后分析就显得尤为重要。本文接下来将介绍内核的内存转储机制以及如何对其进行分析。


    内核的内存转储机制

    由于 Linux 的开放性的缘故,在 Linux 下有好几种内存转储机制。下面将对它们分别做简要的介绍。

    LKCD

    LKCD(Linux Kernel Crash Dump) 是 Linux 下第一个内核崩溃内存转储项目,它最初由 SGI 的工程师开发和维护。它提供了一种可靠的方法来发现、保存和检查系统的崩溃。LKCD 作为 Linux 内核的一个补丁,它一直以来都没有被接收进入内核的主线。目前该项目已经完全停止开发。

    Diskdump

    Diskdump 是另外一个内核崩溃内存转储的内核补丁,它由塔高 (Takao Indoh) 在 2004 年开发出来。与 LKCD 相比,Diskdump 更加简单。当系统崩溃时,Diskdump 对系统有完全的控制。为避免混乱,它首先关闭所有的中断;在 SMP 系统上,它还会把其他的 CPU 停掉。然后它校验它自己的代码,如果代码与初始化时不一样。它会认为它已经被破坏,并拒绝继续运行。然后 Diskdump 选择一个位置来存放内存转储。Diskdump 作为一个内核的补丁,也没有被接收进入内核的主线。在众多的发行版中,它也只得到了 RedHat 的支持。

    Netdump

    RedHat 在它的 Linux 高级服务器 2.1 的版本中,提供了它自己的第一个内核崩溃内存转储机制:Netdump。 与 LKCD 和 Diskdump 将内存转储保存在本地磁盘不同,当系统崩溃时,Netdump 将内存转储文件通过网络保存到远程机器中。RedHat 认为采用网络方式比采用磁盘保的方式要简单,因为当系统崩溃时,可以在没有中断的情况下使用网卡的论询模式来进行网络数据传送。同时,网络方式对内存转储文件提供了更好的管理支持。与 Diskdump 一样,Netdump 没有被接收进入内核的主线,目前也只有 RedHat 的发行版对 Netdump 提供支持。

    Kdump

    Kdump 是一种基于 kexec 的内存转储工具,目前它已经被内核主线接收,成为了内核的一部分,它也由此获得了绝大多数 Linux 发行版的支持。与传统的内存转储机制不同不同,基于 Kdump 的系统工作的时候需要两个内核,一个称为系统内核,即系统正常工作时运行的内核;另外一个称为捕获内核,即正常内核崩溃时,用来进行内存转储的内核。 在本文稍后的内容中,将会介绍如何设置 kump。

    MKdump

    MKdump(mini kernel dump) 是 NTT 数据和 VA Linux 开发另一个内核内存转储工具,它与 Kdump 类似,都是基于 kexec,都需要使用两个内核来工作。其中一个是系统内核;另外一个是 mini 内核,用来进行内存转储。与 Kdump 相比,它有以下特点:

    • 将内存保存到磁盘。
    • 可以将内存转储镜像转换到 lcrash 支持格式。
    • 通过 kexec 启动时,mini 内核覆盖第一个内核。

    各种内存转储分析工具

    与具有众多的内存转储机制一样,Linux 下也有众多的内存转储分析工具,下面将会逐一做简单介绍。

    Lcrash

    Lcrash 是随 LKCD 一起发布的一个内内存储分析工具。随着 LKCD 开发的停止,lcrash 的开发也同时停止了。目前它的代码已经被合并进入 Crash 工具中。

    Alicia

    Alicia (Advanced Linux Crash-dump Interactive Analyzer,高级 Linux 崩溃内存转储交互分析器 ) 是一个建立在 lcrash 和 Crash 工具之上的一个内存转储分析工具。它使用 Perl 语言封装了 Lcrash 和 Crash 的底层命令,向用户提供了一个更加友好的交互方式和界面。Alicia 目前的开发也已经停滞。

    Crash

    Crash 是由 Dave Anderson 开发和维护的一个内存转储分析工具,目前它的最新版本是 5.0.0。 在没有统一标准的内存转储文件的格式的情况下,Crash 工具支持众多的内存转储文件格式,包括:

    • Live linux 系统
    • kdump 产生的正常的和压缩的内存转储文件
    • 由 makedumpfile 命令生成的压缩的内存转储文件
    • 由 Netdump 生成的内存转储文件
    • 由 Diskdump 生成的内存转储文件
    • 由 Kdump 生成的 Xen 的内存转储文件
    • IBM 的 390/390x 的内存转储文件
    • LKCD 生成的内存转储文件
    • Mcore 生成的内存转储文件

    使用 Crash 分析内存转储文件的例子

    通过前面的学习,你现在可能已经跃跃欲试了。本文接下来的部分,将以 kdump 为例子,向大家演示如何设置系统、如何产生内存转储文件以及如何对内存转储文件进行分析。

    kdump 的安装设置

    如前面所述,支持 kdump 的系统使用两个内核进行工作。目前一些发行版,如 RedHat 和 SUSE 的 Linux 都已经编译并设置好这两个内核。如果你使用其他发行版的 Linux 或者想自己编译内核支持 kdump,那么可以根据如下介绍进行。

    安装 kexec

    1. 使用 root 用户登录系统。
    2. 使用 wget 从 Internet 上下载 kexec。
    3. 解压并安装 kexec 到系统中。

    配置系统内核和捕捉内核都需要的内核选项:

    • 在 "Processor type and features."选项中启用"kexec system call"。
    • 在"Filesystem" -> "Pseudo filesystems." 中启用"sysfs file system support"。
    • 在"Kernel hacking."中启用"Compile the kernel with debug info"。

    配置捕捉内核的与架构无关的选项:

    • 在"Processor type and features"中启用"kernel crash dumps"。
    • 在"Filesystems" -> "Pseudo filesystems"中启用"/proc/vmcore support"。

    配置捕捉内核的与架构相关的选项:

    Linux 内核支持多种 CPU 架构,这里只介绍捕捉内核在 i386 下的配置

    • 在"Processor type and features"中启用高端内存支持。
    • 在"Processor type and features"中关闭多处理器支持。
    • 在"Processor type and features"中启用"Build a relocatable kernel"。
    • 在"Processor type and features"->"Physical address where the kernel is loaded"中,为内核设置一个加载起始地址。在大多数的机器上,16M 是一个合适的值。

    加载新的系统内核

    1. 编译系统内核和捕捉内核。
    2. 将重新编译好的内核添加到启动引导中,注意不要将捕捉内核添加到启动引导菜单中。
    3. 给系统内核添加启动参数"crashkernel=Y@X",这里,Y 是为 dump 捕捉内核保留的内存,X 是保留部分内存的开始位置。在 i386 的机器上,设置"crashkernel=64M@16M"。
    4. 重启机器,在启动菜单中选择新添加的启动项,启动新的系统内核。

    加载捕捉内核

    在系统内核引导完成后,需要将捕捉内核加载到内存中。使用 kexec 工具将捕捉内核加载到内存:


    触发内核崩溃

    在捕捉内核被加载进入内存后,如果系统崩溃开关被触发,则系统会自动切换进入捕捉内核。触发系统崩溃的开关有 panic(),die(),die_nmi() 内核函数和 sysrq 触发事件,可以使用其中任意的一个来触发内核崩溃。不过,在让内核崩溃之前,我们还需要做一些安装设置。

    Crash 工具的安装设置

    Crash 目前的最新的版本是 5.0.0, 你可以从它的官方网站下载最新的版本。下载完成后对其进行解压安装。


    生成内存转储文件

    现在已经设置好 Kdump 和 crash,现在可以使用前面介绍的系统崩溃开关中的任意一个来引发系统崩溃来生成一个内存转储文件,并可以使用 crash 对其进行分析。

    首先,触发系统崩溃,这里使用 sysrq 触发事件。


    紧接着,系统会自动启动捕捉内核。待完全启动进入捕捉内核后,通过以下命令保存内存转储文件。


    将在当前目录生成一个 mydumpfile 文件。

    分析内存转储文件

    现在有了一个内存转储文件,接下来使用 crash 对其进行分析


    这里 vmlinux 是带调试信息的内核。如果一切正常,将会进入到 crash 中,如图 1 所示。

    在该提示符下,可以执行 crash 的内部命令。通过 crash 的内部命令,可以查看寄存器的值、函数的调用堆栈等信息。在图 2 中,显示了执行 bt命令后得到的函数调用的堆栈信息。

     

     

    通常在出现系统崩溃后,大家会担心再次出现故障,但是发现系统各日志中并没有记录到任何死机前后的信息,无法分析故障原因,认为已经无药可救。但是,实际上,Linux 有多种机制来保证发生系统崩溃后,可以获取有价值的信息用以分析问题。确定是硬件故障,还是应用程序bug 导致的。

      Linux 中,有如下几种方法来获取各种崩溃时产生的信息。

      1.Core dump

      Core dump 通常用来调试应用程序错误,当某些应用程序运行出现异常崩溃时,可以开启系统的 core dump 功能,来得到一个程序崩溃时的内存信息,用来分析崩溃原因:

      在/etc/profile里加上(或者修改)一条:

      ulimit -c 0

      运行命令:sysctl -w "kernel.core_name_format=/coredump/%n.core"

      该命令意思是指core文件放在/coredump目录下,文件名是进程名+.core

      2.Diskdump

      diskdump工具提供了在单机上创建和采集vmcore(kernel dump) 的能力,而无须使用网络。当内核本身出现崩溃的时候,当前的内存和CPU状态以及相关的信息都会被保存到一个支持diskdump的磁盘上的保留分区上。在下一次重新启动的时候,当系统重新启动,diskdump的初始化脚本会从保留分区中读取保存的信息并创建一个vcore文件,然后这个文件被再次存放到/var/crash/目录下,文件名为127.0.0.1-

      如下是一个配置 HP SCSI 设备上启用 diskdump 的过程,如果不是 HP SCSI 设备(即设备名为 /dev/sdX的形式),则无须执行第三、四两个步骤。但需要在第一步前先执行命令: modprobe

      diskdump

      第一步:编辑 /etc/sysconfig/diskdump文件,将一个空白分区的设备名填入后保存退出,例如:

      DEVICE=/dev/cciss/c0d0p2

      第二步:初使化 dump 设备

      #service diskdump initialformat

      警告:该分区的所以数据会丢失。

      第三步:使用 cciss_dump 模块替换当前的 cciss 模块:

      在 /etc/modprobe.conf 找到如下行:

      alias scsi_hostadapter cciss

      修改为:

      alias scsi_hostadapter cciss_dump

      再增加一行:

      options cciss_dump dump_drive=1

      注:假设diskdump文件中配置的为 /dev/cciss/c0d[#a]p[#b], 请设置为: options cciss_dump dump_drive=[#a]

      第四步:重建 initrd 文件:

      #mv /boot/initrd-`uname -r`.img /boot/initrd-`uname -r`.img.old

      #mkinitrd /boot/initrd-`uname -r`.img `uname -r`

      第五步:设置 diskdump 服务能够开机自启动:

      # chkconfig diskdump on

      3.Netdump

      如果使用红旗DC4.0 或 3.0 版本系统,是不能支持 diskdump 的,可以利用netdump 来达到输出vmcore 的目的。但是Netdump要求至少有一个服务器以及任意数目的客户端。服务器用来接收客户端死机时的信息,客户端是经常死机的机器。

      (一)服务器配置:

      (1).检验netdump服务器是否安装完毕:

      rpm -q netdump-server

      如果未安装,请在光盘 RedFlag/RPMS/ 目录中找到 netdump-server 打头的软件包,执行命令:

      rpm -ivh netdump-server-x.x.x.rpm (x为版本号)

      进行安装。

      (2).服务器包安装后,用命令:

      passwd netdump

      更改用户的密码.

      (3).打开服务:

      chkconfig netdump-server on

      (4).运行服务器:

      service netdump-server start

    (二)客户端配置:

      (1).校验客户端是否已安装

      rpm -q netdump

      如果未安装,在光盘 RedFlag/RPMS/ 目录中找到 netdum 打头的软件包,执行命令:

      rpm -ivh netdump-x.x.x.rpm (x为版本号)

      安装.

      (2).编辑文件/etc/sysconfig/netdump,添加如下行:

      DEV=eth0

      NETDUMPADDR=172.16.81.182

      NETDUMPMACADDR=00:0C:29:79:F4:E0

      172.16.81.182指 netdump 服务器地址。

      (3).运行下面的命令,出现提示符时输入密码:

      service netdump propagate

      (4).打开客户端:

      chkconfig netdump on

      (5).运行客户端:

      service netdump start

      (6).测试

      为了测试netdump的配置是否正确,在netdump客户机上做下面操作:

      cp /usr/share/doc/netdump-xxxxxx/crash.c .

      gcc -DKERNEL -DMODULE -I/lib/modules/$(uname -r)/build/include -c crash.c

      insmod ./crash.o

      这会造成系统崩溃,你会在netdump服务器的/var/crash/<客户端IP>/目录下,看到一个核心转储。当客户机正在转储数据到服务器的时候,你会看到一个名叫“vmcore-incomplete"的文件。当转储结束后,该文件会改名成 "vmcore"。"vmcore"文件的大小会变化,可能达到几个GB.在一个内存是512M的系统上,上面的测试会产生大约510M的vmcore文件。

      怎么判断网卡是否支持netdump功能?

      内核调试工具netdump需要网卡驱动支持netpoll功能。netpoll的目的是让内核在网络和I/O子系统尚不能完整可用时,依然能发送和接收数据包。主要用于网络控制台(net console)和远程内核调试(KGDBoE)中。实现netpoll功能,主要是要实现kernel中的poll_controller函数,该函数定义:void (*poll_controller)(struct net_device *dev)。该函数的作用是在缺少设备中断的情况下,还能对控制器做出响应。几乎所有的poll_controller函数都定义成如下形式:

      void my_poll_controller(struct net_device *dev) {

      disable_device_interrupt(dev);

      call_interrupt_handler(dev->irq, dev);

      enable_device_interrupt(dev);

      }

    所以,poll_controller只是模拟了来自指定设备的中断。一个最简单的判断一个网卡驱动是否这次支持netpoll功能的方法是安装内核源代码,然后在代码树 /usr/src/kernel-<version>中搜索HAVE_POLL_CONTROLLER的定义, grep -r "HAVE_POLL_CONTROLLER" /usr/src/linux-<version>/drivers/net示例如下:

      # grep -r "HAVE_POLL_CONTROLLER" /usr/src/linux-2.4/drivers/net

      /usr/src/linux-2.4/drivers/net/3c59x.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/3c59x.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/e100/e100_main.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/e100/e100_main.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/e1000/e1000_main.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/eepro100.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/eepro100.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/pcnet32.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/pcnet32.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/tg3.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/tg3.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/tlan.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/tlan.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/tulip/tulip_core.c:#ifdef HAVE_POLL_CONTROLLER

      /usr/src/linux-2.4/drivers/net/tulip/tulip_core.c:#ifdef HAVE_POLL_CONTROLLER

      从输出可以看到,3c59x, e100, e1000, eepro100, pcnet32, tg3, tlan和tulip都支持netpoll。

      如果系统使用了这些网卡,那么系统应该支持netpoll,那么就支持netdump。

      如果希望进一步确认网卡是否是使用这些网卡,可以查看/etc/modules.conf:

      # cat /etc/modules.conf

      alias eth1 e100

      alias eth0 3c59x

      4.SysRq

      SysRq组合键是一组"魔术组合键",只要内核没有被完全锁住,键盘还能够使用,不管内核在做什么事情,使用这些组合键可以立即打印出内核的信息。

      使用sysrq组合键是了解系统目前运行情况的最好方式。如果系统出现挂起的情况或者在诊断一些和内核相关,比较怪异,比较难重现的问题的时候,使用sysrq键是一个比较好的方式。

      为了安全起见,默认SysRq组合键是关闭的。

      打开这个功能,运行:

      # echo 1 > /proc/sys/kernel/sysrq

      关闭这个功能:

      # echo 0 > /proc/sys/kernel/sysrq

      如果想让此功能一直生效,在/etc/sysctl.conf里面设置kernel.sysrq的值为1. 重新启动以后,此功能将会自动打开。

      kernel.sysrq = 1

      因为打开sysrq键的功能以后,有终端访问权限的用户将会拥有一些特殊的功能。因此,除非是要调试,解决问题,一般情况下,不要打开此功能。如果一定要打开,请确保您的终端访问的安全性。

    如何触发一个sysrq事件?

      有几种方式可以触发sysrq事件。在带有AT键盘的一般系统上,在终端上输入一下组合键:

      Alt+PrintScreen+[CommandKey]

      例如,要让内核导出内存信息(CommandKey "m"),您应该同时按下Alt 和 Print Screen 键,然后按下 m 键. 提示: 此组合键在Xwindows上是无法使用的。所以,您先要切换到文本虚拟终端下。如果您现在是在图形界面,可以按Ctrl+Alt+F1切换到虚拟终端。

      当我触发一个sysrq事件的时候,结果保存在什么地方?

      当一个sysrq命令被触发,内核将会打印信息到内核的环形缓冲并输出到系统控制台。此信息一般也会通过syslog输出到/var/log/messages.

      有时候,可能系统已经无法响应,syslogd可能无法记录此信息。在这种情况下,建议您配置一个串口终端来收集这个信息。

      那些类型的sysrq事件可以被触发?

      sysrq功能被打开后,有几种sysrq事件可以被触发。不同的内核版本可能会有些不同。但有一些是共用的:

      * m - 导出关于内存分配的信息

      * t - 导出线程状态信息

      * p - 到处当前CPU寄存器信息和标志位的信息

      * c - 故意让系统崩溃(在使用netdump或者diskdump的时候有用)

      * s - 立即同步所有挂载的文件系统

      * u - 立即重新挂载所有的文件系统为只读

      * b - 立即重新启动系统

      * o - 立即关机(如果机器配置并支持此项功能)

      故障分析

      虽然我们可以通过上述的几种方法来获取应用程序或操作系统崩溃时的各种信息,但是分析这些问题有一定难度。

      常见问题

      软件相关

      系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,此类问题多数与应用程序Bug有关,不一定在所有相同配置系统中都会产生,但是一旦触发该Bug,就有可能发生崩溃。

      系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,也有一些情况是新增的应用需要做一定的操作系统配置,没有设置的话,也有可能出现资源利用问题,导致崩溃发生。

      系统平时运行一切正常,自从新实施了一项应用后,频繁发生崩溃现象,也有一些情况是应用的版本与操作系统版本不匹配,应用软件所需的系统库文件版本不对应,容易引发应用程序崩溃。

      系统平时运行正常,近期没有任何新增应用,也没有更改系统配置,却接连发生多次崩溃现象。此类问题多数是压力增大,超出了硬件所能承受的负载,耗尽资源,发生崩溃。

      系统平时运行正常,近期无新增应用,系统负载也不高,却发生崩溃现象。不排除操作系统本身的问题,有可能某种操作诱发了一个系统Bug,发生崩溃。

      硬件相关

      新增内存后,系统经常发生崩溃现象,此类问题有可能是32位机器配置了超过12GB的内存,但没有使用 hugemem 核心导致,具体原因可参见第一节中的说明。

      机器使用期限较长,某个硬件发生故障,也会导致系统崩溃的发生。

      新配置的机器经常发生崩溃现象,有可能硬件较新,而驱动程序版本较低,一般可通过升级驱动解决,驱动一般集成在内核当中,常见的办法是升级内核版本

     
    展开全文
  • Python Crash Course

    2017-10-18 00:32:27
    Python Crash Course.Python Crash Course.Python Crash Course.Python Crash Course
  • Android Crash之Native Crash分析

    万次阅读 2016-06-19 10:54:08
    前言上一篇给大家介绍了Android Crash中的Java Crash分析,我们可以知道Java Crash一般会弹出提示框告诉我们程序崩溃了,通常使用Crash工具都能够捕获到;本篇博客来谈谈如何针对Native Crash进行分析,它相对与Java...

    前言

    上一篇给大家介绍了Android Crash中的Java Crash分析,我们可以知道Java Crash一般会弹出提示框告诉我们程序崩溃了,通常使用Crash工具都能够捕获到;本篇博客来谈谈如何针对Native Crash进行分析,它相对与Java层面的Crash有什么特点?如何判断程序Crash是因为Native层导致的?我们怎么去分析它?下面我们一个一个解答这些问题。

    Native Crash在Android上的特点

    1. 出错时界面不会弹出提示框提醒程序崩溃(Android 5.0以下)
    2. 出错时会弹出提示框提醒程序崩溃(Android 5.0以上)
    3. 程序会直接闪退到系统桌面
    4. 这类错误一般是由C++层代码错误引起的
    5. 绝大部分Crash工具不能够捕获

    我们在实际Android开发的时候,可能会引入第三方的一些so库或者自己开发相应的so库供程序使用,然而so库一般是通过c或者c++开发的。Android开发者通过java层的JNI机制调用Native语言写的函数,然而Natice语言也可以调用java层的函数。 如果有同学不明白的话,建议先去了解下JNI的相应技术,总的来说通过JNI技术,就让我们让Java世界跟Native世界可以联系在一起,也因为这个特性,让Java具有跨平台的特性。

    如果想了解如何通过Android Studio制作so库,笔者前面的一篇文章可以帮到你:http://blog.csdn.net/wwj_748/article/details/51274580

    Native Crash是如何产生的?

    上一节我们谈到so库是同通过Native语言开发的,自然在Android中使用so库的时候发生的Crash,就是我们所说的Native Crash。为了更好的让大家知道Native Crash是如何产生的,下面笔者举一个例子:

    Java层定义Native方法

    TestJNI

    本地方法跟普通的Java方法的区别在于方法声明多了native关键字。

    JNI层实现Native方法

    实现Native方法

    这里我们制造一个Native Crash,空指针异常。

    通过Java调用Native方法

    调用Native方法

    要调用Native方法需要先加载我们开发好的so库,通过System.loadLibrary(“so名字”);来调用,然后在通过java调用声明的native方法。

    Native Crash如何分析?

    既然要分析就必须找到可以分析的东西,我们在分析Java层Crash的时候是通过logcat日志找到对应的出错代码,然而Native层Crash也是可以logcat日志来进行分析的。

    这里我们截取上面制造的crash在logcat显示的日志:

    出错信息

    这个是什么鬼,看不懂啊有木有。这个出错信息是我们调用native函数时打印出来的日志,只是简单的描述出错信号,出错地址还有进程号,看这个是完全摸不着调的。不过系统还是会提供相关有用的日志,我们在Android Studio查看logcat的时候需要做一下过滤。

    添加DEBUG过滤项

    在logcat添加完”DEBUG”的过滤项之后,我们就能得到以下log:

    DEBUG

    这下子可分析的内容就多起来了,我们逐个来看看:
    - 进程信息:pid表示进程号,tid表示线程号,name表示进程名
    - 错误信号:signal 11表示信号的数字,SIGSEGV表示信号的名字,code 1(SEGV_MAPERR)表示出错代码,fault addr 00000000 表示出错的地址。
    - 寄存器快照:进程收到错误信号时保存下来的寄存器快照,一共有15个寄存器。
    - 堆栈信息:##00表示栈顶,##01调用#00,以此往下都是嵌套的调用关系,直至到栈顶。

    这里参考了:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=27&extra=page%3D4

    我们在栈顶就已经看到我们出错的地方了:

    #00  pc 00000730  /data/app-lib/com.devilwwj.jnidemo-1/libJNIDemo.so (Java_com_devilwwj_jnidemo_TestJNI_createANativeCrash)

    pc 00000730 表示出错的地址,后面可以看到我加载了libJNIDemo.so库,接着是我们前面声明的Native方法,通过这种方法我们就能准确的找到出错的地方。

    从上面的分析我们可以看到,so库崩溃时会产生信号异常,如果我们能够捕获到信号异常,相当于我们也能够顾捕获到Android Native崩溃了。

    总结

    关于Native Crash的特点、产生原因、分析过程已经给大家做了简单的分析,这一块内容是初学者在分析错误的时候最头痛的地方,因为他不知道如何下手,也希望通过这篇文章能帮助到大家对Native Crash分析有个初步的认识,关于这一块还有很多东西可以讲,比如具体的signal有哪些,Linux下的信号机制是怎样的,怎样才能够捕获到信号等等,关于Native层的Crash捕获,我们有没有第三方的开发工具能帮助到我们,这里就要隆重推荐大家使用Bugly,可以说是业内领先的崩溃捕获工具,不仅能够帮助我们获取到完整的错误堆栈,还能够将出错的上下文环境参数(比如系统版本、设备信息、内存信息等)详细的展现出来,大家不妨可以尝试下。最后,感谢大家的阅读。

    展开全文
  • 编写Linux crash工具插件扩展crash命令

    千次阅读 2020-08-14 22:41:42
    我的需求是用crash工具dump出Netfilter的某个hook点所有hook所属模块的名字。 我的方法如下,首先找到模块地址: crash px nf_hooks[2][0] =>var crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk ...

    当前时间,周五晚10点45分左右。

    我的需求是用crash工具dump出Netfilter的某个hook点所有hook所属模块的名字。

    我的方法如下,首先找到模块地址:

    crash px nf_hooks[2][0] =>var
    crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk -F '=' '/owner/{print $2}'
    

    如此会得到一个列表,比如:

    0x1234
    0x6678
    0x8641
    0x4570
    ...
    

    显然,这些地址都是module结构体,我需要执行下面的命令得到其name字段:

    crash module.name $addr_above
    

    然而,我必须一个一个输入,或者使用文件redirect:

    crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk -F '=' '/owner/{print $2}' >./aa
    crash module.name <./aa 
    

    这太麻烦了。

    我想知道能不能在crash命令行编写脚本或者使用类似xargs,awk BEGIN,END之类的,比如使用下面这种:

    crash list nf_hook_ops.list -s nf_hook_ops.owner -H $var |awk -F '=' '/owner/{print $2}' | xargs -i    module.name {}
    

    从而一次性获得所有结果,免除手工输入的麻烦。

    我试了,crash命令没有办法被管道化。

    经过询问,了解到crash有一个extend命令可以加载extension扩展插件,研究了一下,比较简单且有意义。

    说白了就是基于crash的API写一个共享库,在crash命令行输入help extend将会显示这样的共享库如何来编码。我基于上述需求简单写了一个,可以用:

    // nfhooks.c
    #include <crash/defs.h>
    
    static int get_field(unsigned long addr, char *name, char *field, void* buf)
    {
    	unsigned long off = MEMBER_OFFSET(name, field);
    
    	if (!readmem(addr + off, KVADDR, buf, MEMBER_SIZE(name, field), name, FAULT_ON_ERROR))
    		return 0;
    	return 1;
    }
    
    void do_cmd(void)
    {
    	unsigned long ops_addr, owner_addr;
    	unsigned long list_addr, base, next;
    	char name[64];
    
    	optind++;
    	base = next = list_addr = htol(args[optind], FAULT_ON_ERROR, NULL);
    
    	do {
    		// 由于list就是nf_hook_ops的第一个字段,因此就不炫技了,强转即可。
    		//get_field(list_addr - MEMBER_OFFSET("nf_hook_ops", "list"), "list_head", "next", &ops_addr);
    		ops_addr = list_addr = next;
    		get_field(ops_addr, "nf_hook_ops", "owner", &owner_addr);
    		get_field(owner_addr, "module", "name", &name[0]);
    		if (list_addr != base)
    			fprintf(fp, "--%s\n", name);
    		} while(get_field(list_addr, "list_head", "next", &next) && next != base);
    }
    
    static struct command_table_entry command_table[] = {
    	{ "nfhooks", do_cmd, NULL, 0},
    	{ NULL },
    };
    
    void __attribute__((constructor)) nfhooks_init(void)
    {
    	register_extension(command_table);
    }
    
    void __attribute__((destructor)) nfhooks_fini(void) { }
    

    编译命令如下:

    gcc -fPIC -shared nfhooks.c -o nfhooks.so
    

    将生成的so放在执行crash命令的目录下,在crash命令行加载之:

    crash> extend nfhooks.so
    ./nfhooks.so: shared object loaded
    

    随后就可以用了:

    # 首先dump出INET IPv4的PREROUTING点的list地址
    crash> px &nf_hooks[2][0]
    $1 = (struct list_head *) 0xffffffff81a71000 <nf_hooks+256>
    crash> nfhooks 0xffffffff81a71000
    --bridge
    --nf_defrag_ipv4
    --iptable_raw
    --nf_conntrack_ipv4
    --iptable_mangle
    --iptable_nat
    crash>
    

    是不是很有意思呢。

    有了这个机制,就可以非常方便地使用readmem来进行Linux内核任意地址任意结构体字段的解析了,你就再也不用抱怨crash命令不够用了,不够用就自己写一个,而自己的写一个的成本非常低,无非就是readmem不断解析结构体,这一切的背后,只需要你对内核足够熟悉即可。

    我之前写过一个手工解析/dev/mem或者vmcore的程序,但和crash插件扩展相比,太low太麻烦了,有了这个机制,以后再也不用干手工活儿了。

    将上面的代码稍微扩展一下,就可以dump出所有协议族,所有hook点的所有模块名字了:

    #include <crash/defs.h>
    
    static int get_field(unsigned long addr, char *name, char *field, void* buf)
    {
    	unsigned long off = MEMBER_OFFSET(name, field);
    
    	if (!readmem(addr + off, KVADDR, buf, MEMBER_SIZE(name, field), name, FAULT_ON_ERROR))
    		return 0;
    	return 1;
    }
    
    #define FAMILY	12
    #define TYPE	8
    
    struct dummy_list {
    	struct dummy_list *next, *prev;
    };
    
    struct dummy_list *iter;
    void do_cmd(void)
    {
    	unsigned long ops_addr, owner_addr;
    	unsigned long list_addr, base, next;
    	char name[64];
    	int i, j;
    
    	optind++;
    	iter = (struct dummy_list *)htol(args[optind], FAULT_ON_ERROR, NULL);
    
    	for (i = 0; i < FAMILY; i++) {
    		for (j = 0; j < TYPE; j++) {
    			fprintf(fp, "at PF: %d  hooknum: %d \n", i, j);
    			base = next = list_addr = (unsigned long)&iter[i*TYPE + j];
    			do {
    				ops_addr = list_addr = next;
    				get_field(ops_addr, "nf_hook_ops", "owner", &owner_addr);
    				get_field(owner_addr, "module", "name", &name[0]);
    				if (list_addr != base)
    					fprintf(fp, "  ----%s\n", name);
    				} while(get_field(list_addr, "list_head", "next", &next) && next != base);
    		}
    	}
    }
    
    static struct command_table_entry command_table[] = {
    	{ "allnfhooks", do_cmd, NULL, 0},
    	{ NULL },
    };
    
    void __attribute__((constructor)) nfhooks_init(void)
    {
    	register_extension(command_table);
    }
    
    void __attribute__((destructor)) nfhooks_fini(void) { }
    

    是不是很简单呢?我从来不记录复杂的东西,简单的才是真美。

    当前时间,周五晚10点45分左右。已经不在996的管辖范围,请继续举报!


    浙江温州皮鞋湿,下雨进水不会胖。

    展开全文
  • linux主机利用crash分析-var-crash-下的vmcore-的dump分析.pdf
  • 自定义Crash

    2013-07-05 15:18:13
    1.程序遇到Crash不会弹出系统的那个Crash对话框,而是我们自己定义的一个Toast 2.我们会把Crash信息收集起来保存到Sdcard,你可以将Crash上传到你的服务器
  • 和你一起终身学习,这里是程序员Android 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容:一、Crash 简介二、搭建Crash 分析kernel ramdump平台三、Crash 命令简介四、使用 Crash...
  • kdump crash

    2019-06-28 15:25:13
    查看kdump状态为failed。...安装crash:sudo yum install crash 运行测试: [yubo.wang@localhost 4g-box]$ sudo crash a.out [sudo] password for yubo.wang: crash 7.2.3-8.el7 Copyright (C) 200...
  • crash分析

    2019-09-13 16:14:16
    1)载入crash crash /boot/vmlinux vmcore /boot/vmlinux-debug 2)载入ko mod -S /opt/huawei/snas/lib 3)查看堆栈 bt 4)列出crash行号 dis -l ffffffffa2d1...
  • Android Crash之Java Crash分析 https://www.jianshu.com/p/8f5fc87c23c5
  • crash处理

    2016-08-06 09:12:30
    crash处理
  • ADB 查看 crash log

    2020-12-08 19:52:35
    有时候项目Crash 了, 我们可以使用adb 查看crash 信息 在终端中输入 adb shell 然后就是查看crash 命令 logcat -b crash 这样就能查看crash 的地方了.
  • crash 工具源码

    2018-04-06 16:24:41
    自测可用的crash 工具源码,比如用arm 32位的,make target=arm
  • 如何分析JAVA crash

    2017-11-16 12:32:22
    如何分析JAVA crash 为什么程序会Crash? 什么是异常? 如何分析JAVA Crash 程序执行时发生了无法处理的异常 崩溃分为 Java Crash 和 Native Crash
  • Crash reporter

    2017-12-04 17:28:00
    crash reporter is a software application whose function is to identify report crash details and to alert when there are crashes, in production or on development / testing environments. Crash ...
  • 保存kernel crash信息的一种方式,文件内为源代码实现。可自行分析。稍加修改即自用。
  • crash unsafe 定义:从库重启后对binlog的重复执行 样例:从库拉取了主库binlog执行后posting未记录到内存中,重启,将会把这条命令再次执行。从库拉取了主库binlog执行后posting未记录到磁盘中,重启,将会把这条...
  • crash用法

    2019-08-01 04:30:05
    You gonna crash on the couch? 你要睡在沙发上吗? 不及物动词 vi. 1. (发出猛烈声音地)碰撞,倒下,坠落The motorcycle crashed into the fence. 摩托车猛地撞在围栏上。 2. (飞机等)坠毁,撞坏An ...
  • Crash收集

    2016-03-18 14:27:00
    Crash对移动端应用的用户留存率、口碑和收入都有非常大的影响!有高达63%的移动用户遭遇Crash,Crash发生在首次启动,21%的用户会选择卸载,Crash发生在使用过程中,70%的用户会给以差评。因此我们要重视Crash的收集...
  • No crash log created (a crash in the crash handler does not produce a crash log). <h2>Steps to reproduce <p>??? (Seems to randomly occur, especially with starting new games, testing scripts, loading ...
  • android Crash

    2015-12-03 16:44:59
    android Crash 腾讯的android Crash http://bugly.qq.com/
  • Crash编译安装

    2020-07-21 16:29:54
    IBM crash教程 从github下载源码 编译时可能需要的依赖 sudo apt-get install libncurses5-dev sudo apt-get install zlib1g-dev 进入crash目录 编译32位ARM的crash:make target=ARM 编译64位ARM的...
  • crash:overview

    2020-05-14 12:19:27
    平台Android10代码中包含crash工具,路径和内容如下: calm.xia@shand20[12:15:30]:~/10_automotive/vendor/sprd/tools/crash$ tree -L 3 . ├── pycrash │ ├── bin │ │ ├── crash -> crash_arm64 │ ...
  • 在电脑上运行程序的时候常常会遇到很多的问题然后提示appcrash错误,为此下面就给你们带来了appcrash问题解决方法,一直遇到这个问题的小伙伴就快来解决一下吧。appcrash事件怎么解决:方法一:1、出现appcrash错误...
  • Android Crash监控

    2020-11-07 18:12:11
    Crash(应用崩溃)是由于代码异常而导致 App 非正常退出,导致应用程序无法继续使用,所有工作都 停止的现象。发生 Crash 后需要重新启动应用(有些情况会自动重启),而且不管应用在开发阶段做得 多么优秀,也无法...
  • crash man手册

    2011-01-11 00:35:53
    crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man,crash man
  • iOS Crash报告分析

    万次阅读 2017-12-15 13:40:15
    dSYM文件 crash报告
  • Linux kernel crash dumps with crash

    千次阅读 2015-12-03 10:53:02
    Software & security Computer games Life topics Hillbilly physics Greatest sites 3D art Model ...Analyzing Linux kernel crash dumps with crash - The one tutorial that h
  • Android Crash 工具

    2019-09-28 20:13:04
    极力推荐Android 开发大总结文章:欢迎收藏 程序员Android 力荐 ,Android 开发者需要的必备技能 本篇文章主要介绍 Android 开发中的部分知识点,通过阅读本篇文章,您将收获以下内容: ...五、Crash...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 116,915
精华内容 46,766
关键字:

crash