嵌入式C语言环境下异常处理方法及装置转让专利

申请号 : CN200810100060.5

文献号 : CN101599039B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 余加强郑伟

申请人 : 华为技术有限公司

摘要 :

本发明实施例提供一种嵌入式C语言环境下的异常处理方法,包括:监控正在运行的需要保护的程序代码片段,如果所述程序代码片段出现异常,则抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常,其中,所述异常处理程序与所述程序代码片段相互独立。本发明还提供一种嵌入式C语言环境下的异常处理装置。

权利要求 :

1.一种嵌入式C语言环境下的异常处理方法,其特征在于,包括:

监控正在运行的需要保护的程序代码片段,如果所述程序代码片段出现异常,则抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;所述程序代码片段为函数、由多个函数组成的模块或由多个模块组成的部件;

根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常,其中,所述异常处理程序与所述程序代码片段相互独立。

2.如权利要求1所述的方法,其特征在于,所述监控正在运行的需要保护的程序代码片段的步骤具为:根据设置的处理异常的粒度,监控所述正在运行的需要保护的程序代码片段。

3.如权利要求1所述的方法,其特征在于,进一步包括:申请用于记录与异常相关的信息的存储空间;

则,在所述程序代码片段出现异常之后,抛出所述异常之前,记录与异常相关的信息。

4.如权利要求1或3所述的方法,其特征在于,所述抛出所述异常具体为:将所述与异常相关的信息打包后传递出去,所述与异常相关的信息至少包括异常类型标识,所述异常类型标识用于表示当前程序代码片段出现的异常的类型。

5.如权利要求4所述的方法,其特征在于,所述根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常的步骤包括:获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识;

确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,由所述异常处理程序处理所述异常。

6.如权利要求5所述的方法,其特征在于,所述确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,由所述异常处理程序处理所述异常的步骤包括:当所述异常类型标识对应的异常类型与能处理的一种特殊的异常类型匹配时,由与该异常类型匹配的异常处理程序处理该异常;

或,当所述异常类型标识对应的异常类型与能处理的至少一种异常类型中的一种异常类型匹配时,由与该异常类型匹配的异常处理程序处理该异常;

或,当存在能处理任何类型异常的异常处理程序时,确定由该匹配任意类型异常的异常处理程序处理所述异常。

7.如权利要求6所述的方法,其特征在于,所述方法进一步包括:如果当前不存在与该异常类型匹配的异常处理程序时,将获得的与异常相关的信息重新传递出去,或者,当都匹配不上时,启动默认处理程序,所述默认处理程序为重启系统。

8.如权利要求4所述的方法,其特征在于,所述根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常的步骤包括:获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识、指定处理方式标识;

确定与所述异常类型标识对应的异常类型所匹配,且与所述的指定处理方式标识对应的处理方式所匹配的异常处理程序,由所述匹配的异常处理程序处理所述异常。

9.如权利要求5所述的方法,其特征在于,所述异常处理程序还能够匹配和处理多种类型的异常。

10.如权利要求5所述的方法,其特征在于,如果有多个与所述异常类型相匹配的异常处理程序,则确定与所述异常类型标识对应的异常类型所匹配的异常处理程序的步骤为:确定与所述异常类型标识对应的异常类型所匹配的,且与所述程序代码片段位置最近的一个异常处理程序。

11.如权利要求1所述的方法,其特征在于,如果所述程序代码片段被调用时出现异常,则由所述异常处理程序处理所述异常之后,还包括:逐级返回所述程序代码片段正常运行后的结果,或者运行与所述异常处理程序相邻且在其之后的程序代码片段。

12.如权利要求2所述的方法,其特征在于,所述设置的处理异常的粒度包括函数级别、模块级别、部件级别中的至少一种,其中,所述模块由多个函数组成,所述部件由多个模块组成。

13.如权利要求8所述的方法,其特征在于,当所述处理方式是容错处理方式,由容错方式的异常处理程序处理所述异常;

当所述处理方式是查错处理方式,由查错方式的异常处理程序处理所述异常,其中,所述异常处理程序与所述程序代码片段相互独立。

14.如权利要求1所述的方法,其特征在于,由具有匹配和捕捉异常功能的宏来匹配和捕捉异常;由具有监控功能的宏来监控正在运行的需要保护的程序代码片段;由具有抛出异常功能的宏来抛出所述异常。

15.一种嵌入式C语言环境下异常处理装置,其特征在于,包括:

监控单元,用于监控正在运行的需要保护的程序代码片段;所述程序代码片段为函数、由多个函数组成的模块或由多个模块组成的部件;

异常抛出单元,用于在所述监控单元发现所述程序代码片段出现异常后,抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;

匹配单元,用于根据获得的所述异常,确定对应的异常处理程序,所述异常处理程序用于处理所述异常抛出单元抛出的异常,其中,所述异常处理程序与所述程序代码片段相互独立。

16.如权利要求15所述的异常处理装置,其特征在于,还包括:信息记录单元,用于记录与所述监控单元发现的所述程序代码片段出现的异常相关的信息,并输出给所述异常抛出单元。

17.如权利要求16所述的异常处理装置,其特征在于,所述异常抛出单元为第一异常抛出单元,用于在所述监控单元发现所述程序代码片段出现异常后,将所述与异常相关的信息打包后传递出去,所述与异常相关的信息至少包括异常类型标识,所述异常类型标识用于表示当前程序代码片段出现的异常的类型。

18.如权利要求17所述的异常处理装置,其特征在于,所述匹配单元为第一匹配单元,用于获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识,并确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,由所述异常处理程序处理所述异常。

19.如权利要求17所述的异常处理装置,其特征在于,所述匹配单元为第二匹配单元,用于获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识、指定处理方式标识,并确定与所述异常类型标识对应的异常类型所匹配,且与所述的指定处理方式标识对应的处理方式所匹配的异常处理程序,由所述异常处理程序处理所述异常。

20.如权利要求15所述的异常处理装置,其特征在于,如果有多个与所述异常的类型相匹配的异常处理程序,所述匹配单元为第三匹配单元,用于根据获得的所述异常,确定与所述异常的类型所匹配的,且与所述程序代码片段位置最近的一个异常处理程序,由所述异常处理程序处理所述异常。

21.如权利要求15所述的异常处理装置,其特征在于,所述监控单元为第一监控单元,用于在一程序执行触发异常时,根据设置的处理异常的粒度监控所述正在运行的需要保护的程序代码片段。

22.一种嵌入式系统,其特征在于,所述系统包括如权利要求15-21任意一项所述的异常处理装置。

说明书 :

嵌入式C语言环境下异常处理方法及装置

技术领域

[0001] 本发明涉及C语言技术,尤其涉及嵌入式C语言环境下异常处理技术。

背景技术

[0002] 异常是指硬件或软件程序在运行时出现的反常情形。在嵌入式C语言环境下,传统的异常处理方法是,当发现异常时,重启系统。以程序异常为例,可以通过CPU的异常识别能力,检查程序运行时是否出现异常,一旦CPU发现程序运行时出现异常,则调用异常处理程序,将包含寄存器、当前堆栈、调用栈在内的异常信息保存下来,然后按统一的方式完成处理。即,对于发生在任务中的异常,调试版本下挂起该任务,在正式版本中重启嵌入式系统,对于发生在中断中的异常,则均以重启嵌入式系统的方式进行处理。
[0003] 发明人经过仔细研究现有技术后发现,随着软件复杂度的日益增加,系统重启需要更长的时间,而产品对系统的中断时间要求越来越短,甚至不希望系统运行时发生中断,而在嵌入式C语言环境下,传统的异常处理方法无法满足这样的需求。

发明内容

[0004] 本发明实施例在于提供一种嵌入式C语言环境下异常处理方法、装置及嵌入式系统,用以实现当异常发生时,缩短系统的中断时间,或者不发生中断。
[0005] 一种嵌入式C语言环境下的异常处理方法,包括:监控正在运行的需要保护的程序代码片段,如果所述程序代码片段出现异常,则抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;所述程序代码片段为函数、由多个函数组成的模块或由多个模块组成的部件;根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常,其中,所述异常处理程序与所述程序代码片段相互独立。
[0006] 一种嵌入式C语言环境下异常处理装置,包括:监控单元,用于监控正在运行的需要保护的程序代码片段;所述程序代码片段为函数、由多个函数组成的模块或由多个模块组成的部件;异常抛出单元,用于在所述监控单元发现所述程序代码片段出现异常后,抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;匹配单元,用于根据获得的所述异常,确定对应的异常处理程序,所述异常处理程序用于处理所述异常抛出单元抛出的异常,其中,所述异常处理程序与所述程序代码片段相互独立。
[0007] 一种嵌入式系统,包括上述异常处理装置。
[0008] 在本发明实施例的嵌入式C语言环境下异常处理方法、装置及嵌入式系统中,如果程序代码片段出现异常,则不是简单的重新运行程序代码片段,而是由独立于程序代码片段的异常处理程序来处理异常,这样,程序在运行时,就不会因为异常而中断运行,满足了产品不希望系统运行时发生中断的需求。
[0009] 在本发明实施例的嵌入式C语言环境下退出或删除线程或进程的方法中,无论是退出或者删除线程或进程,都可以释放处理线程或进程抛出的异常所占用的资源,这样,当其他线程或进程需要使用这些资源时,不会因为删除或退出的线程或进程所抛出的异常仍然占用资源而导致其他线程或进程无法使用这些资源。另外,还可以由其他线程删除所需要删除的线程,从而可以实现跨线程删除线程时的异常处理。

附图说明

[0010] 图1为本发明实施例的嵌入式C语言环境下异常处理方法的流程图;
[0011] 图2为本发明实施例的嵌入式C语言环境下异常处理装置的结构示意图;
[0012] 图3为本发明实施例的不同的异常处理程序对应不同的异常类型的示意图;
[0013] 图4为本发明的嵌入式C语言环境下异常处理方法一具体实施例的流程图;
[0014] 图5为本发明实施例的堆空间存储异常相关信息的存储布局示意图;
[0015] 图6为本发明实施例的try块的实现流程图;
[0016] 图7为本发明实施例的except块的实现流程图;
[0017] 图8为本发明实施例的捕捉某种特定异常的实现流程图;
[0018] 图9为本发明实施例的捕捉处理指定异常的实现流程图;
[0019] 图10为本发明实施例的捕捉和处理某一异常区间内的异常的实现流程图;
[0020] 图11为本发明实施例的throw块的实现流程图;
[0021] 图12为本发明实施例的异常处理的精细管理方法的流程图;
[0022] 图13为本发明实施例的退出线程或进程的方法的流程图;
[0023] 图14为本发明实施例的退出线程或进程的装置的结构示意图;
[0024] 图15为本发明实施例的删除线程或进程的方法的流程图;
[0025] 图16为本发明实施例的删除线程或进程的装置的结构示意图。

具体实施方式

[0026] 为使本发明的目的、技术方案及优点更加清楚明白,以下参照附图并举实施例,对本发明作进一步详细说明。
[0027] 在本发明实施例中,对于C语言环境下嵌入式系统中的异常可以根据不同场景编写具有针对性的异常处理程序,进行局部异常处理并尝试恢复,而不必对所有异常都作重启系统处理,在异常处理完毕后继续执行,从而提高正常流程下的代码运行效率,也简化了编程。在C语言环境下嵌入式系统中异常处理框架(方便理解,可称为异常处理装置)的实现不依赖于编译器,并且提供给用户对异常处理框架进行精细管理的方法。
[0028] 本发明实施例中,提供了多种嵌入式C语言环境下的异常处理方法,其中的一种方法如图1所示,包括:
[0029] 步骤S101:监控正在运行的需要保护的程序代码片段;
[0030] 步骤S102:如果所述程序代码片段出现异常,则抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;
[0031] 需要说明的是:本发明实施例的方案不仅适用于软件异常,还适用于硬件异常;当发生硬件异常后,可以尝试恢复异常,避免重启系统;
[0032] 步骤S103:根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常,其中,所述异常处理程序与所述程序代码片段相互独立。为了提供对异常抛出时异常处理级别的精细管理,在本发明实施例中,所述监控正在运行的需要保护的程序代码片段的步骤具体为:根据设置的处理异常的粒度,监控正在运行的需要保护的程序代码片段;
[0033] 当一程序执行触发异常时,在一种实现下,当正在运行的需要保护的程序代码片段大于或等于设置的处理异常的粒度时,则监控所述正在运行的需要保护的程序代码片段;
[0034] 当正在运行的需要保护的程序代码片段小于设置的处理异常的粒度时,则不监控所述正在运行的需要保护的程序代码片段,也就是说,就不需要执行后续的步骤;这里的,所述设置的处理异常的粒度包括函数级别、模块级别、部件级别中的至少一种,其中,所述模块由多个函数组成,所述部件由多个模块组成。例如,用户在调试阶段设置处理异常的粒度为函数级别;当代码稳定后,用户设置处理异常的粒度为模块级别,则代码在抛出异常时只识别模块级的异常。
[0035] 在本发明实施例中,所述方法进一步包括:申请用于记录与异常相关的信息的存储空间;则,在所述程序代码片段出现异常之后,抛出所述异常之前,记录与异常相关的信息。应当理解的是:将与异常相关的信息记录在申请的存储空间中。
[0036] 在本发明实施例中,所述抛出所述异常的步骤,在一种实现下,具体为:将所述与异常相关的信息打包后传递出去,这里,所述与异常相关的信息至少包括异常类型标识,应当说明的是:异常类型标识是用于表示当前程序代码片段出现的异常的类型的信息,形式上可以采用数字,或者字符,或者数字和字符的组合,例如:采用不同的字符串表示不同异常类型。
[0037] 应当理解的是:本发明实施例适用不同类型的异常,在一种实现下,预先可以给不同的具体异常类型分配不同的标识,例如:将异常统一分成a、b、c、d、e、f(小类),并且同时用另一个标识区分哪些是软件异常,哪些是硬件异常(大类),例如:1表示软件异常;0表示硬件异常;需要说明的是:这仅是一个例子,不用于限制本发明实施例方案。
[0038] 在本发明实施例中,根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常的步骤,在一种实现下,可以包括:
[0039] 获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识;
[0040] 确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,由所述异常处理程序处理所述异常。因此,本发明实施例针对不同类型的异常进行不同处理,避免现有技术在遇到异常时,重启系统,导致系统中断时间长的问题。
[0041] 确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,由所述异常处理程序处理所述异常的步骤包括:
[0042] 当所述异常类型标识对应的异常类型与能处理的一种特殊的异常类型匹配时,由与该异常类型匹配的异常处理程序处理该异常;
[0043] 或,当所述异常类型标识对应的异常类型与能处理的至少一种异常类型中的一种异常类型匹配时,由与该异常类型匹配的异常处理程序处理该异常,其中,能处理的至少一种异常类型可以是数组指定的类型,或者是异常区间内的类型;
[0044] 或,当存在能处理任何类型异常的异常处理程序时,确定由该匹配任意类型异常的异常处理程序处理所述异常。
[0045] 需要理解的是:在一种实现下,可以由宏确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,这个宏的形式为EXCEPT,该宏可以带有异常类型参数,也可以不带有异常类型参数;
[0046] 在该宏带有异常类型参数的情况下,具体匹配过程可以包括:获得线程异常信息(即与异常相关的信息);判断线程异常信息中的异常类型标识是否与异常类型参数中的一种匹配;如果匹配,则执行相应的异常处理程序;如果不匹配,则重新传递(抛出)异常信息。在该宏不带有异常类型参数的情况下,任何类型的异常都将被相应异常处理程序处理,换句话说,EXCEPT宏一旦获得异常,就交由与所述程序代码片段位置最近的一个异常处理程序去处理异常,也就起到了捕捉所有类型异常的作用。该宏不带有异常类型参数时,包括异常类型标识的异常信息还是传递到except块宏作处理,用户编写的异常处理程序可以不加区分的进行统一处理。
[0047] 本发明实施例的方法进一步包括:如果当前不存在与该异常类型匹配的异常处理程序时,将获得的与异常相关的信息重新传递出去,或者,当都匹配不上时,启动默认处理程序,所述默认处理程序为重启系统。
[0048] 为了进一步的提供对异常处理方式的精细管理,在本发明实施例中,根据获得的所述异常,确定相应的异常处理程序,由所述异常处理程序处理所述异常的步骤,在另一种实现下,可以包括:
[0049] 获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识、指定处理方式标识;需要说明的是:可以通过不同的指定处理方式标识表示不同的指定处理方式,例如:1表示容错的处理方式;0表示查错的处理方式。
[0050] 确定与所述异常类型标识对应的异常类型所匹配,且与所述的指定处理方式标识对应的处理方式所匹配的异常处理程序,由所述异常处理程序处理所述异常。其中,处理方式可以为容错或查错。
[0051] 当所述处理方式是容错处理方式,由容错方式的异常处理程序处理所述异常;当所述处理方式是查错处理方式,由查错方式的异常处理程序处理所述异常,其中,所述异常处理程序与所述程序代码片段相互独立。
[0052] 如果当前不存在与该异常类型匹配,且与指定的处理方式匹配的异常处理程序时,将获得的与异常相关的信息重新传递出去,或者,当都匹配不上时,启动默认处理程序,所述默认处理程序为重启系统。
[0053] 因此,本发明实施例不仅可以实现针对不同类型的异常进行不同的处理,而且还能根据用户设置的方式对异常以不同的处理方式进行处理,例如,在开发阶段,对异常的处理主要方法是捕获异常处理错误并输出错误,而在开发完成产品发布时,异常处理的主要方法是容错恢复。本发明实施例中的异常处理程序还能够匹配和处理多种类型的异常。
[0054] 如果有多个与所述异常类型相匹配的异常处理程序,则确定与所述异常类型标识对应的异常类型所匹配的异常处理程序的步骤为:确定与所述异常类型标识对应的异常类型所匹配的,且与所述程序代码片段位置最近的一个异常处理程序。
[0055] 如果所述程序代码片段被调用时出现异常,则由所述异常处理程序处理所述异常之后,还包括:逐级返回所述程序代码片段正常运行后的结果,或者运行与所述异常处理程序相邻且在其之后的程序代码片段;从而进一步提高正常流程下的代码运行效率。
[0056] 在一种实现下,由匹配和捕捉异常功能的宏来匹配和捕捉异常;由具有监控功能的宏来监控正在运行的需要保护的程序代码片段;由具有抛出异常功能的宏来抛出所述异常。
[0057] 具体的,程序代码片段可以是指函数,也可以是指由多个函数组成的模块,还可以是指由多个模块组成的部件,当然,程序代码片段还可以是其他级别的程序段,这里不再一一列举。在嵌入式C语言环境下,可以由具有监控功能的宏来监控程序代码片段,例如可以由封装C语言的setjmp()函数的宏。
[0058] 当程序代码片段在运行过程中出现异常时,需要抛出异常,而在抛出异常之前,可以记录与异常相关的信息,这样,抛出异常时,可以抛出与异常相关的信息。与异常相关的信息既可以包括软件异常信息,也可以包括硬件异常信息。在嵌入式C语言环境下,可以由具有抛出异常功能的宏来抛出异常,例如可以由封装C语言的longjmp()函数的宏。
[0059] 针对需要保护的程序代码片段,可以建立至少一个异常处理程序。每个异常处理程序可以匹配和处理一种类型的异常,也可以匹配和处理多种类型的异常。不同的异常处理程序可以处理同一种类型的异常,当异常被抛出时,可以从中选择一个异常处理程序来处理这种类型的异常,例如,可以选择一个与所述程序代码片段最近的一个异常处理程序处理所述异常。具体的,假设某个程序代码片段之后分别有程序A、程序B和程序C等能够处理同一个异常的异常处理程序,当程序代码片段抛出异常时,如果没有特殊设置,则一般都由程序A(在程序代码片段之后,在所有的能够处理所述异常的异常处理程序中位置相对于该程序代码片段最靠前)来处理所述异常。
[0060] 需要说明的是,异常处理程序与程序代码片段是相互独立的,这样至少有两个优点:第一个优点是,程序代码片段在运行过程中如果没有出现异常,则异常处理程序不会被执行,从而不影响程序代码片段的正常运行,客观上也提高了程序代码片段的运行效率;第二个优点是,可以给用户提供是否由异常处理程序来处理异常或者由哪种异常处理程序来处理异常的选择。
[0061] 在实际应用中,程序代码片段可能是在被调用过程中出现异常,由与所述异常的类型相匹配的异常处理程序处理所述异常之后,可以逐级返回的是程序代码片段正常运行后的结果。例如,函数A调用函数B,函数B调用函数C,如果函数C在运行时发生异常,并且存在与异常的类型相匹配的异常处理程序,则可以由异常处理程序处理异常,处理异常后,函数C可以正常运行,其正常运行的结果可以返回给函数B,函数B再将函数B的运行结果返回给函数A。由此可见,即使函数B调用函数C时,函数C运行出现异常,但对于函数A和函数B来说,这个或这些异常都是不被发现的,函数A和函数B得到的分别是函数B正常运行的结果和函数C正常运行的结果。另外,由与所述异常的类型相匹配的异常处理程序处理所述异常之后,也可以运行所述异常处理程序之后的程序代码片段。还是以上面的例子为例,即使由异常处理程序处理异常,但不再返回执行函数C,而是执行后续的程序代码片段,后续的程序代码片段可以是指与异常处理程序相邻且在其位置之后的程序代码片段,也可以是指异常处理程序之后的任意一个程序代码片段。
[0062] 在嵌入式C语言环境下,可以由由用C语言实现的具有匹配和捕捉异常功能的宏来匹配和捕捉异常,例如可以由封装C语言的setjmp()函数被调用后返回非0值的else分支的宏。
[0063] 其中的一种嵌入式C语言环境下异常处理装置(也可以称为异常处理框架)如图2所示,包括:
[0064] 监控单元201,用于监控正在运行的需要保护的程序代码片段;
[0065] 异常抛出单元202,用于在监控单元201发现所述程序代码片段出现异常后,抛出所述异常,所述异常包括软件异常、硬件异常中的至少一种;
[0066] 匹配单元203,用于根据获得的所述异常,确定对应的异常处理程序,所述异常处理程序用于处理所述异常抛出单元抛出的异常,其中,所述异常处理程序与所述程序代码片段相互独立。
[0067] 在嵌入式C语言环境下,将具有监控功能的宏模块化即监控单元,例如可以是封装C语言的setjmp()函数的宏。
[0068] 另外,上述装置还可以包括:
[0069] 信息记录单元204,用于记录与监控单元201发现的所述程序代码片段出现的异常相关的信息,并输出给所述异常抛出单元202。这样,异常抛出单元202在抛出异常时,可以抛出与异常相关的信息。与异常相关的信息既可以包括软件异常信息,也可以包括硬件异常信息。在C语言环境下,将具有抛出异常功能的宏模块化即异常抛出单元202,例如可以是封装C语言的longjmp()函数的宏。
[0070] 异常抛出单元202为第一异常抛出单元,用于在监控单元201发现所述程序代码片段出现异常后,将所述与异常相关的信息打包后传递出去,所述与异常相关的信息至少包括异常类型标识,所述异常类型标识用于表示当前程序代码片段出现的异常的类型。
[0071] 匹配单元203为第一匹配单元,用于获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识,并确定与所述异常类型标识对应的异常类型所匹配的异常处理程序,由所述异常处理程序处理所述异常。
[0072] 匹配单元203为第二匹配单元,用于获得传递过来的与异常相关的信息,所述与异常相关的信息中包含异常类型标识、指定处理方式标识,并确定与所述异常类型标识对应的异常类型所匹配,且与所述的指定处理方式标识对应的处理方式所匹配的异常处理程序,由所述异常处理程序处理所述异常。例如,可以设置函数级别的异常处理程序,也可以设置模块级别的异常处理程序,还可以设置部件级别的异常处理程序,假设对应这三个级别的异常处理程序都能够处理同一个类型的异常,但处理方式各不相同。用户可以选择处理异常的级别,假设用户选择了模块级别,其对应的异常处理程序的处理方式是容错处理,当需要保护的程序代码片段在运行过程中出现异常,则处理异常的就是模块级别对应的异常处理程序,即,对异常采取容错方式处理。
[0073] 处理方式可以包括容错和查错等多种方式,当程序代码片段出现异常时,可以根据设置的处理方式处理异常。例如,如果设置的处理方式是容错处理方式,则可以使用容错方式的异常处理程序处理异常。再例如,如果设置处理方式是查错处理方式,则可以使用查错方式的异常处理程序处理异常,其中,异常处理程序与程序代码片段相互独立。
[0074] 如果有多个与所述异常的类型相匹配的异常处理程序,匹配单元203为第三匹配单元,用于根据获得的所述异常,确定与所述异常的类型所匹配的,且与所述程序代码片段位置最近的一个异常处理程序,由所述异常处理程序处理所述异常。
[0075] 在一程序执行触发异常时,监控单元201为第一监控单元,用于根据设置的处理异常的粒度监控所述正在运行的需要保护的程序代码片段。例如:当设置的处理异常的粒度为模块级别时,而所述正在运行的需要保护的程序代码片段是函数级别,则就不需要监控所述正在运行的需要保护的程序代码片段;当设置的处理异常的粒度为函数级别时,而所述正在运行的需要保护的程序代码片段是模块级别,则监控所述正在运行的需要保护的程序代码片段;针对需要保护的程序代码片段,可以建立至少一个异常处理程序。每个异常处理程序可以匹配和处理一种类型的异常,也可以匹配和处理多种类型的异常。
[0076] 不同的异常处理程序可以处理同一种类型的异常,当异常抛出单元202抛出异常时,可以由匹配单元203从中选择一个异常处理程序来处理这种类型的异常,例如,可以选择一个与所述程序代码片段最近的一个异常处理程序处理所述异常。
[0077] 在实际应用中,程序代码片段可能是在被调用过程中出现异常,在匹配单元203确定与所述异常的类型相匹配的异常处理程序,由该异常处理程序处理所述异常之后,程序代码片段可以逐级返回正常运行后的结果。在嵌入式C语言环境下,将由C语言实现的具有匹配和捕捉异常功能的宏模块化即匹配单元203,例如可以是封装C语言的setjmp()函数被调用后返回非0值的else分支的宏。
[0078] 需要说明的是,由于不同的异常处理程序可以适用于不同的异常,为方便识别异常类型,可以给不同的异常类型分配不同的标识,例如:将异常统一分成a、b、c、d、e、f(小类),并且同时用另一个标识区分哪些是软件异常,哪些是硬件异常(大类),例如:1表示软件异常;0表示硬件异常。具体的,如图3所示,首先获得传递过来的与异常相关信息(简称异常信息),该异常信息中包含异常类型标识,经过宏的匹配,确定与该异常类型标识对应的异常类型匹配的异常处理程序,由相应的异常处理程序处理相应的异常类型的异常。
[0079] 除上述方法实施例和异常处理框架实施例外,本发明还提供了嵌入式系统,所述系统包括上述异常处理装置(即异常处理框架)。具体请参见上述对异常处理框架的描述,这里不再赘述。
[0080] 除上述方法实施例外,本发明还提供了另外一个方法实施例。具体的,如图4所示,包括:
[0081] 步骤S401:执行程序代码;
[0082] 步骤S402:判断是否触发异常,如果是,则转步骤S403,否则,转步骤S401;
[0083] 步骤S403:根据处理异常的粒度,确定与粒度对应的try块(为描述方便,这里用try块表示具有监控功能的宏);
[0084] 步骤S404:判断try块是否有except块(为描述方便,这里用except块表示具有捕捉和匹配异常功能的宏),如果是,转步骤S406,否则,转步骤S405;
[0085] 步骤S405:确定更高一级粒度对应的try块,转步骤S404;
[0086] 步骤S406:判断except块是否能够处理异常,如果是,转步骤S407,否则,转步骤S405;
[0087] 步骤S407:执行except块的代码,转步骤S401。
[0088] 本发明实施例首先在嵌入式C语言环境下建立异常记录信息,建立异常相关信息的存储和传递模型,最终实现异常关联的机制和用户接口。
[0089] 1.关于异常记录信息:
[0090] 表1为异常记录信息的一种表现形式。
[0091]
[0092] 表1
[0093] 在嵌入式C语言环境下,为了实现异常处理,需要定义异常记录结构,将异常信息保存在该结构中,传递给except块,except块可以根据异常记录信息来决定处理的方式。异常记录信息如下列代码中的注释所示:
[0094]
[0095]
[0096] 2:关于异常相关信息的存储和传递模型
[0097] 在嵌入式C语言环境下,为支持异常嵌套处理和对多线程异常的处理,需要存储异常相关信息,并根据其生命周期的特点选择适当的存储和传递模型。异常相关信息包括:(1)每个try块保存其运行上下文环境的env信息(info);(2)发生异常后的异常记录信息(即前面定义的VOS_SEH_REC);(3)各线程的异常状态控制表。
[0098] 从具有抛出异常功能的宏到具有匹配和捕捉异常功能的宏的信息采用线程范围的栈来存储和传递,其中,env信息所需存储空间需要满足try块最大嵌套层次的深度,而异常记录信息存储空间则需要满足一次嵌套的最大深度,因此,可以考虑以线程为单位,在线程创建后,分配线程堆空间来存储异常相关信息,存储布局示意可以参照图5。
[0099] env信息是各线程正常运行期间高度动态的信息,每个线程都保留一份。exc信息(info)则只在线程运行异常情况下才出现,各线程间可以共享使用。
[0100] env信息把所有可回溯的环境记录串联起来形成异常范围表,在throw块(为描述方便,这里用throw块表示具有抛出异常功能的宏)操作时通过访问该表来获得相匹配的except块,该表存储单元需记录的信息如表2所示:
[0101]
[0102] 表2
[0103] 具体的数据结构如下:
[0104]
[0105]
[0106] exc信息把异常记录信息记录下来,在throw块(相当于上述装置中的异常抛出单元)操作时,将该结构做为信息参数传递给相匹配的except块(相当于上述装置中的匹配单元)来处理,如果其中发生异常嵌套,则将信息进行串联。需记录的信息如表3所示:
[0107]信息有效标志 异常记录信息
[0108] 表3
[0109] 具体数据结构如下:
[0110]
[0111] 各线程间共享的SEH_EXC_INFO缓冲区分配控制信息表如表4所示:
[0112]异常最大信息块数 已分配信息块数 空闲异常信息块链表
[0113] 表4
[0114] 具体数据结构如下:
[0115]
[0116] 在线程创建成功后,分配的异常状态控制表(exc ctrl)信息如表5所示:
[0117]
[0118] 表5
[0119] 具体数据结构如下:
[0120]
[0121] 其中,ulSehStatusFlag标志有六种状态,分别是:SEH_STAT_NON(无异常情况下的初始值必须为0),SEH_STAT_UNHANDLE(未处理异常),SEH_STAT_HANDLED(已处理),SEH_STAT_CONTINUE_SEARCH(继续回溯异常处理块),SEH_STAT_CONTINUE_REDO(从异常处重新执行)和SEH_STAT_RESTART(重启进程或单板)。
[0122] 对线程异常范围表以单向链表方式组织,按栈序操作,本发明实施例提供如下功能的接口函数:
[0123]
[0124] 对线程异常信息缓冲表的申请释放可提供如下接口功能函数:
[0125] SEH_EXC_INFO*SHE_ExcInfoBufAlloc();//申请线程异常信息缓冲表[0126] VOS_UINT32 SEH_ExcInfoBufFree(SEH_EXC_INFO*pSehExcInfo);//释放线程异常信息缓冲表
[0127] 3.关于异常处理流程的实现和用户接口设计
[0128] 标准C库中提供的setjmp()、longjmp()函数可以提供非本地局部跳转的机制。在嵌入式C语言环境下,不依赖编译器实现异常关联机制,可以采用setjmp的封装来实现try块,并在识别异常后调用longjmp来提供throw块,except块则是setjmp调用后返回非0值的else分支。
[0129] 一、线程异常状态控制表的构造
[0130] 为实现上述接口,首先需要构造线程异常状态控制表。各线程共享异常信息控制块在系统初始化阶段从系统堆空间申请,保存在指向结构SEH_INFO_BUF_CTRL的指针g_pSehInfoBufCtrl中。
[0131] 在VxWorks下,任务创建成功后,申请系统堆空间保存SEH_TH_CTRL,使用taskVarAdd将指向SEH_TH_CTRL的指针g_pSehThCtrl内容保存在任务变量中,在try块中可通过局部变量访问g_pSehThCtrl,其值由VxWorks切换,同时将该堆空间记录在系统任务资源总表中。
[0132] 在Linux下,使用pthread_key_create创建key句柄,并保存在key句柄指针g_pThKey中,线程创建成功后,申请系统堆空间保存SEH_TH_CTRL,调用pthread_setspecific完成指向SEH_TH_CTRL的指针g_pSehThCtrl内容保存,在try块中通过局部变量保存pthread_getspecific的返回值(该线程的g_pSehThCtrl内容)来操作本线程的异常状态控制表,同时将该堆空间记录在系统线程资源总表中。
[0133] 当本任务或线程自动退出时,对g_pSehThCtrl指向的系统堆空间进行释放;当删除其他任务或线程时,对记录在系统资源总表中的其他任务或线程资源进行释放。
[0134] 二、try块的设计
[0135] try块的实现流程如图6所示,包括:
[0136] 步骤S601:开始执行try块宏;
[0137] 步骤S602:判断所述try块对应的粒度是否小于设置的处理异常的粒度,如果是,转步骤S608,否则,转步骤S603;
[0138] 步骤S603:获得当前线程异常状态控制表的地址,转步骤S604;
[0139] 步骤S604:从线程异常状态控制表的空闲范围块链表中申请一个Unit块,转步骤S605;
[0140] 步骤S605:初始化Unit块的biIntFlag,将Unit块压入线程异常范围链表,初始化异常状态控制表的相关项,转步骤S606;
[0141] 步骤S606:调用setjmp()函数,转步骤S607;
[0142] 步骤S607:判断是否返回0,如果是,则转步骤S608,否则,转步骤S609;
[0143] 步骤S608:正常处理,转步骤S610;
[0144] 步骤S609:异常处理,转步骤S610;
[0145] 步骤S610:结束执行try块宏,转步骤S611;
[0146] 步骤S611:判断是否需要回溯,如果是,则转步骤S612,否则,转步骤S613;
[0147] 步骤S612:重新抛出异常;
[0148] 步骤S613:判断是否需要复位,如果是,则转步骤S614,否则,转步骤S615;
[0149] 步骤S614:重新启动进程或单板处理;
[0150] 步骤S615:判断是否恢复执行,如果是,转步骤S616,否则,转步骤S617;
[0151] 步骤S616:根据CPU特点执行异常恢复操作;
[0152] 步骤S617:try块结束处理。
[0153] 需要说明的是,步骤S608和S609(即图中虚线部分)为用户处理代码,即,用户需要进行的流程,例如需要保护的程序代码片段等正常的程序代码。
[0154] 具体的,try块从线程异常状态控制表的空闲范围块链表中可以动态申请一个记录单元,如果超过线程try块最大嵌套层数ulMaxScopeLayer,则触发系统默认异常处理。正常情况下,经过少量初始化操作后,将其压入(push)到线程异常范围链表中,然后在if语句中调用setjmp,对应用程序的正常处理流程代码形成监控,当被监控的代码片段中有硬件或软件异常抛出时,该程序能够恢复到由此setjmp保存的执行点。为区分setjmp的返回值是第一次调用(0值),还是longjmp调用的返回(非0值),用线程异常状态控制表中的ulSehStatusFlag记录,当返回非0时,表示当前异常处理状态,其含义为,匹配该try块的except块是否被找到,或者需要进一步回溯,或者从异常处重新执行,或者需要复位进程或复位单板。此外,try块的实现还需要考虑对异常处理级别的精细管理进行支持。
[0155] try块的流程可以通过如下方式实现:
[0156]
[0157] try块的实现需要做到不依赖于编译器,无法通过编译器的文法识别来找到try块的结束点并自动添加结束代码,因此,需要设计一个由应用程序调用的SEH_TRY_END,来完成try块的结束处理,完成对异常状态的清除处理。
[0158]
[0159]
[0160] 三、except块的设计
[0161] 在try块之后,需要提供except块的机制,它实际上就是SEH_TRY_BEG封装的if语句配对的else分支,可以对throw块抛出的异常类型进行处理,同时支持异常处理方式的精细处理。具体实现流程如图7所示,包括:
[0162] 步骤S701:开始执行except块宏;
[0163] 步骤S702:关闭正常处理分支的作用域或前一个异常处理方式的作用域;
[0164] 步骤S703:判断是否是当前异常处理方式,如果是,转步骤S704,否则,转步骤S708;
[0165] 步骤S704:将Unit块弹出线程异常范围表;
[0166] 步骤S705:将Unit块释放到线程异常状态控制表的空闲范围块链表;
[0167] 步骤S706:设置异常已处理的状态;
[0168] 步骤S707:执行异常处理程序代码,这里的,异常处理程序代码即异常处理代码;
[0169] 步骤S708:转下一个异常处理方式的except块或者结束异常处理。
[0170] 封装代码如下:
[0171]
[0172] SEH_EXCEPT可以实现对任意类型异常的捕捉,为支持对异常类型的过滤,即捕获特定类型的异常,本发明实施例进一步提供三种格式的封装。
[0173] (1)捕捉某种特定异常
[0174] 实现流程如图8所示,包括:
[0175] 步骤S801:开始执行except块宏;
[0176] 步骤S802:关闭正常处理分支的作用域或前一个异常处理方式的作用域;
[0177] 步骤S803:判断是否是当前异常处理方式,如果是,转步骤S804,否则,转步骤S810;
[0178] 步骤S804:将Unit块弹出线程异常范围表;
[0179] 步骤S805:判断是否匹配异常类型,如果是,转步骤S807,否则,转步骤S806;
[0180] 步骤S806:重新抛出异常;
[0181] 步骤S807:将Unit块释放到线程异常状态控制表的空闲范围块链表;
[0182] 步骤S808:设置异常已处理的状态;
[0183] 步骤S809:执行异常处理程序代码;
[0184] 步骤S810:转下一个异常处理方式的except块或者结束异常处理。
[0185] 实现代码如下:
[0186]
[0187] (2)捕捉处理指定异常
[0188] 实现流程如图9所示,包括:
[0189] 步骤S901:开始执行except块宏;
[0190] 步骤S902:关闭正常处理分支的作用域或前一个异常处理方式的作用域;
[0191] 步骤S903:判断是否是当前异常处理方式,如果是,转步骤S904,否则,转步骤S910;
[0192] 步骤S904:将Unit块弹出线程异常范围表;
[0193] 步骤S905:判断是否匹配数组指定的异常类型,如果是,转步骤S907,否则,转步骤S906;
[0194] 步骤S906:重新抛出异常;
[0195] 步骤S907:将Unit块释放到线程异常状态控制表的空闲范围块链表;
[0196] 步骤S908:设置异常已处理的状态;
[0197] 步骤S909:执行异常处理程序代码;
[0198] 步骤S910:转下一个异常处理方式的except块或者结束异常处理。
[0199] 实现代码如下:
[0200]
[0201] (3)捕捉和处理某一异常区间内的异常
[0202] 实现流程如图10所示,包括:
[0203] 步骤S1001:开始执行except块宏;
[0204] 步骤S1002:关闭正常处理分支的作用域或前一个异常处理方式的作用域;
[0205] 步骤S1003:判断是否是当前异常处理方式,如果是,转步骤S1004,否则,转步骤S1010;
[0206] 步骤S1004:将Unit块弹出线程异常范围表;
[0207] 步骤S1005:判断是否匹配异常区间内的异常类型,如果是,转步骤S1007,否则,转步骤S1006;
[0208] 步骤S1006:重新抛出异常;
[0209] 步骤S1007:将Unit块释放到线程异常状态控制表的空闲范围块链表;
[0210] 步骤S1008:设置异常已处理的状态;
[0211] 步骤S1009:执行异常处理程序代码;
[0212] 步骤S1010:转下一个异常处理方式的except块或者结束异常处理。
[0213] 实现代码如下:
[0214]
[0215] 此外,本发明实施例还在except块中提供给应用层做进一步处理的相关操作宏接口如下:
[0216] (1)获得异常记录信息
[0217] #detine SEH_GET_RECORD(pSehRec)\
[0218] ((pSehRec)=&(__try__pSehThCtrl->pSehExcInfo.seh_rec))
[0219] (2)获得异常类型
[0220] #define SEH_GET_TYPE(SehType)\
[0221] ((SehType)=__try__pSehThCtrl->pSehExcInfo.seh_rec.ulSehType)[0222] (3)设置异常嵌套层数
[0223] #define SEH_GET_NEST_COUNT(NestCount)\
[0224] (NestCount)=__try__pSehThCtrl->ulExceptNestCnt
[0225] (4)设置异常处理状态
[0226] #define SEH_SET_STATUS(SehStatus)\
[0227] __try__pSehThCtrl->ulSehStatusFlag=(SehStatus)
[0228] 四、throw块的设计
[0229] 调用throw的地方有两处,一处是在系统捕获硬件异常时,调用throw块,将异常通知到except块,另一处则是try中的函数主动调用throw抛出软件异常。对这两种情况,这里提供统一的抛出操作,即,获得线程异常范围表中位于栈顶的存储单元(但不弹出),对单元内容进行赋值,可通过函数SEH_ThrowInner实现。
[0230] 实现流程如图11所示,包括:
[0231] 步骤S1101:执行ThrowInner()函数;
[0232] 步骤S1102:判断参数是否合法,如果是,则转步骤S1103,否则,转步骤S1112;
[0233] 步骤S1103:获取当前线程异常状态控制表的地址;
[0234] 步骤S1104:获得线程异常范围链表的栈顶存储单元;
[0235] 步骤S1105:判断是否有匹配的try块和except块,如果是,则转步骤S1106,否则,转步骤S1112;
[0236] 步骤S1106:判断是否有共享异常信息缓存或者抛出的异常记录是否是异常现场记录,如果是,转步骤S1107,否则,转步骤S1111;
[0237] 步骤S1107:分配共享异常信息缓存;
[0238] 步骤S1108:判断是否有缓存,如果是,则转步骤S1109,否则,转步骤S1112;
[0239] 步骤S1109:初始化缓存,设置未处理异常标志;
[0240] 步骤S1110:执行except块代码;
[0241] 步骤S1111:设置异常处理标志;
[0242] 步骤S1112:进行默认的异常处理。
[0243] 实现代码如下:
[0244]
[0245]
[0246] 对程序抛出的软件异常情况,大多数硬件异常信息可以屏蔽。简化后的宏封装接口首先初始化抛出的异常记录信息,然后调用SEH_ThrowInner函数,实现如下:
[0247]
[0248] 对于当前excpet块无法处理的情况,前面已在SEH_EXCEPT_ONE、SEH_EXCEPT_VAR和SEH_EXCEPT_IN的情况下描述,将pSehThCtrl->ulSehStatusFlag设置为需要进一步回溯状态SEH_STAT_CONTINUE_SEARCH后执行rethrow,重新抛出接口实现如下:
[0249] #define SEH_RETHROW()\
[0250] SEH_ThrowInner(&(pSehThCtrl->pSehExcInfo->seh_rec))
[0251] 五、框架精细管理的实现
[0252] 对框架的精细管理有两个方面。一方面提供对异常抛出时处理模块级别的精细管理,另一方面提供对异常处理方式的精细管理。
[0253] (1)异常抛出时处理模块级别的精细管理
[0254] 代码抛出异常时,可以根据精细程度查找try块,为此定义宏SEH_HANDLE_LEVEL,用户通过配置该宏可以保存期望的异常处理框架的精细度。该宏的值默认为FUNC_LEVEL(函数级)。用户可以根据需要将该宏的值配置为MODULE_LEVEL或者COMPONENT_LEVEL。
[0255] 用户在设置try块保护代码时,同时可以指定try块的配置级别SEH_Level。在try块的设计中,可以看到,当SEH_Level>=SEH_HANDLE_LEVEL时,框架中代码抛出异常时相应的try块才被识别。因此,在开发的不同阶段,用户只需要配置SEH_HANDLE_LEVEL,就可以对异常处理框架的精细度进行控制。例如,用户在调试阶段设置SEH_HANDLE_LEVEL为FUNC_LEVEL(函数级别),所有try块均可被识别;当代码稳定后,用户设置SEH_HANDLE_LEVEL为FUNC_LEVEL为MODULE_LEVEL,则代码在抛出异常时只识别模块级的异常。
[0256] 框架对配置的异常处理级别的判断和支持在try块中实现,其实现和流程在try块的设计和图8中已做了说明。
[0257] (2)异常处理方式的精细管理
[0258] 用户在嵌入式C语言环境下开发的不同阶段,对异常的处理会有不同的处理方式。例如,在开发阶段,对异常的处理主要方法是捕获异常处理错误并输出错误,而在开发完成产品发布时,异常处理的主要方法是容错恢复。因此,异常处理的精细管理为用户提供框架,使得用户在不同阶段编写异常处理代码时,不需要覆盖以前的代码而只是简单的指定处理方式,针对不同的处理方式编写不同的异常处理代码。
[0259] 为此,可以设置宏EXCEPTION_HANDLE_METHOD保存用户当前的处理方式,在except块捕获异常时,指定处理方式method(EXCEPTION_CHECK、EXCEPTION_TOLARENT以及其他用户定义的方式)method与当前的处理方式EXCEPTION_HANDLE_METHOD相同的except块才能处理对应try块的异常。用户可按照如下方式使用异常处理框架:
[0260]
[0261] 对异常处理方法精细管理的支持实现和流程在except块的设计部分和图9中已进行了描述。
[0262] (3)异常处理框架的精细管理方法
[0263] 实现流程如图12所示,包括:
[0264] 步骤S1201:执行保护程序代码的try块;
[0265] 步骤S1202:判断当前级别是否不小于用户配置的级别,如果是,转步骤S1203,否则,转步骤S1209;
[0266] 步骤S1203:执行需要保护的程序代码;
[0267] 步骤S1204:判断需要保护的程序代码是否抛出异常,如果是,转步骤S1205,否则,转步骤S1203;
[0268] 步骤S1205:确定对应的except块;
[0269] 步骤S1206:判断是否符合用户设置的异常处理方式,如果是,转步骤S1207,否则,转步骤S1208;
[0270] 步骤S1207:执行异常处理程序代码;
[0271] 步骤S1208:转下一个异常处理方式,转步骤S1206;
[0272] 步骤S1209:忽略当前try块保护,转步骤S1203。
[0273] 具体的,用户可以配置异常处理级别和异常处理手段。例如,遇到try块时,首先判断当前try块的级别是否不小于用户配置的异常处理级别,如果是,则对代码进行保护,否则,忽略该try块的保护机制。对于try块保护的代码,如果抛出异常,则寻找对应的except块,如果找到的except块的处理手段与用户配置的处理手段相符,则进行相应的异常处理,否则,寻找相应的下一处理手段的except块。
[0274] 六、用户接口及使用方法
[0275] 本发明实施例提供了两类外部接口:一类是搭建异常框架的接口,包括用于识别代码片段的try块的接口SEH_TRY_BEG和SEH_TRY_END,用于与代码片段匹配的异常处理程序except块的接口SEH_EXCEPT(匹配所有异常)、SEH_EXCEPT_ONE(匹配某一类异常)、SEH_EXCEPT_VAR(匹配异常类型可变)和SEH_EXCEPT_IN(匹配特定类型号区间的异常),以及用于抛出异常的throw块的SEH_THROW接口;另一类是在异常处理框架中,为方便应用程序进一步处理异常,或者根据需要更灵活的控制异常处理流程所使用的处理接口,包括SEH_GET_RECORD(获取异常记录信息)、SEH_GET_TYPE(获取异常类型)和SEH_SET_STATUS(设置异常处理状态),上述接口均以宏方式提供,并在异常处理框架内部使用。用户可在代码中通过如下方式使用该异常处理框架:
[0276]
[0277]
[0278] 本发明除提供上述异常处理方法外,还提供了嵌入式C语言环境下退出线程或进程的方法和删除线程或进程的方法。
[0279] 退出线程或进程的方法的实现流程如图13所示,应用于线程主动退出的场景,包括:
[0280] 步骤S1301:获得线程或进程需要退出的信息。
[0281] 步骤S1302:检查需要退出的线程或进程所抛出的异常是否仍然占用资源,如果是,转步骤S1303,否则,转步骤S1304;
[0282] 步骤S1303:释放所述占用的资源;
[0283] 步骤S1304:退出所述线程或进程。
[0284] 检查需要退出的线程或进程所抛出的异常是否仍然占用资源具体可以包括:检查需要退出的线程或进程是否已抛出异常;如果是,则检查已抛出的异常是否仍然占用资源。
[0285] 具体的,可以为用户提供线程退出的接口操作VOS_ExitThread,该接口函数在退出线程前,首先检查当前线程是否有异常处理的资源尚未释放,如果有,则对try块中抛出异常所占用的资源进行检查和释放,之后执行退出线程的操作。
[0286] 其中的一种嵌入式C语言环境下退出线程或进程的装置可以如图14所示,包括:信息获得单元1401,用于获得线程或进程需要退出的信息;资源检查单元1402,用于在信息获得单元1401获得线程或进程需要退出的信息后,检查需要退出的线程或进程所抛出的异常是否仍然占用资源;资源释放单元1403,用于在资源检查单元1402检查出需要退出的线程或进程所抛出的异常仍然占用资源,则释放所述占用的资源;线程或进程退出单元
1404,用于在资源释放单元1403释放所述占用的资源后,退出所述线程或进程。
[0287] 删除线程或进程的方法的实现流程如图15所示,应用于当前线程或进程被其他线程或进程删除的场景,包括:
[0288] 步骤S1501:确定需要删除的线程或进程。
[0289] 步骤S1502:检查需要删除的线程或进程所抛出的异常是否仍然占用资源,如果是,转步骤S1503,否则,转步骤S1504;
[0290] 步骤S1503:释放所述占用的资源;
[0291] 步骤S1504:删除所述线程或进程。
[0292] 检查需要删除的线程或进程所抛出的异常是否仍然占用资源具体可以包括:检查需要删除的线程或进程是否已抛出异常;如果是,则检查已抛出的异常是否仍然占用资源。
[0293] 具体的,若线程1抛出异常后切换到线程2,线程2需要执行对线程1的删除操作,在本发明实施例中,线程2对线程1中抛出的异常所占用的资源进行处理后再删除线程1。
[0294] 在Linux下,线程2删除线程1是通过给线程1发送信号实现的,因此,可以在线程1中注册信号的处理函数handler中对已抛出的异常进行处理。在Linux下,对于跨进程删除时的异常处理可以采用同样的方法进行处理。
[0295] 在VxWorks下,删除任务的函数taskDelete允许通过函数taskDeleteHookAdd()注册钩子函数,因此,可在删除任务之前,注册钩子函数对要删除的任务的异常进行处理。
[0296] 对于以上两种操作系统,本发明实施例提供统一的处理手段。具体的,提供VOS_KillExHandle()函数,在Linux系统下注册为删除线程(进程)的信号的handler,在vxWorks下注册为退出钩子。VOS_KillExHandle()函数通过获得被删除线程的异常状态控制表中的信息获得当前要处理的异常,然后对异常及其占用的资源进行相应的处理。
[0297] 其中的一种C语言环境下删除线程或进程的装置如图16所示,包括:
[0298] 确定单元1601,用于确定需要删除的线程或进程;
[0299] 资源检查单元1602,用于在确定单元1601确定需要删除的线程或进程后,检查需要删除的线程或进程所抛出的异常是否仍然占用资源;
[0300] 资源释放单元1603,用于在资源检查单元1602检查出需要删除的线程或进程所抛出的异常仍然占用资源,则释放所述占用的资源;
[0301] 线程或进程删除单元1604,用于在资源释放单元1603释放所述占用的资源后,删除所述线程或进程。
[0302] 综上所述,本发明实施例实现了在嵌入式C语言环境下不依赖于编译器的可精细管理的异常处理方法。本发明实施例提供的用户接口可以将用户的编码和异常处理分离,使得用户在使用嵌入式C语言环境进行程序开发时,通过使用简单的宏接口即可实现基于异常处理的程序设计,从而更关注代码正常分支的开发。对异常框架的可精细管理的设计使得用户可以根据需要调整异常处理的级别,例如,在调试阶段可以将异常处理定在函数级,以尽量抓取程序的异常,而在代码稳定后,产品上网运行时将异常处理级别定为部件级,忽略函数级的异常处理,只针对模块出现的异常进行统一处理。
[0303] 针对现有技术中用户无法根据自己的需要对异常处理的粒度和方式进行控制的状况,本发明实施例在上述不依赖于编译器的异常处理方法和异常处理框架中实现将异常处理动态配置到函数、模块或者组件的机制,以及配置异常处理的机制,从而实现对异常处理方法和异常处理框架的精细管理。使得用户可以根据自己的需要对异常处理框架和处理方法进行精细管理。用户对异常处理框架和处理方法的精细管理包括两个方面:
[0304] 一方面,在开发的不同阶段,用户可以根据需要将异常处理动态配置到函数、模块、组件等不同级别,从而达到对异常处理框架的精细管理。例如,在产品开发阶段,用户为了尽量找到引发异常的错误,可以将异常处理级别配置为函数级别,在异常处理保护的代码中,函数抛出的异常都会被函数的异常处理机制捕获并处理;当产品开发结束发布时,代码已经较为稳定,为了提高性能,用户可以将异常处理级别配置为模块级甚至部件级,异常处理的机制在模块或部件范围内起作用,抛出的异常会被本模块或部件的异常处理机制捕获并统一处理。
[0305] 另一方面,用户对同一段保护的代码可以做不同的异常处理,并可以在异常处理框架中配置异常处理方法,在不同的情况下使不同的异常处理方法生效。例如,对同一段保护的代码,用户的异常处理可以有查错和容错至少两种处理方式,在代码开发时使用查错方式尽量找到引发异常的错误,而在产品发布时使用容错方式对异常进行恢复处理。用户可以在异常处理框架中配置异常处理方式为查错或者容错。
[0306] 以及,在本发明实施例的嵌入式C语言环境下异常处理方法、装置及嵌入式系统中,如果程序代码片段出现异常,则不是简单的重新运行程序代码片段,而是使用独立于程序代码片段的异常处理程序来处理异常,这样,程序在运行时,就不会因为异常而中断运行,满足了产品不希望系统运行时发生中断的需求。
[0307] 以及,针对现有技术中的异常处理机制不支持跨线程和跨进程删除时的异常处理,本发明实施例在嵌入式C环境下不依赖于编译器的异常处理方法和异常处理框架中提供了线程主动退出和跨线程(进程)删除时的方法。在本发明实施例的嵌入式C语言环境下退出或删除线程或进程的方法中,无论是退出或者删除线程或进程,都可以释放处理线程或进程抛出的异常所占用的资源,这样,当其他线程或进程需要使用这些资源时,不会因为删除或退出的线程或进程所抛出的异常仍然占用资源而导致其他线程或进程无法使用这些资源。另外,还可以由其他线程删除所需要删除的线程,从而可以实现跨线程删除线程时的异常处理。
[0308] 本领域普通技术人员可以理解实现上述实施例的嵌入式C语言环境下异常处理的过程可以通过程序指令相关的硬件来完成,所述的程序可以存储于可读取存储介质中,该程序在执行时执行上述方法中的对应步骤。所述的存储介质可以如:ROM/RAM、磁碟、光盘等。
[0309] 最后需要说明的是,本发明所有的实施例都可以应用于嵌入式C语言环境下、非嵌入式C语言环境下。
[0310] 以上所述仅是本发明的优选实施方式,应当指出,对于本技术领域的普通技术人员来说,在不脱离本发明原理的前提下,还可以作出若干改进和润饰,这些改进和润饰也应视为本发明的保护范围。