一种避免主机在访问共享设备造成异常死锁的方法转让专利

申请号 : CN200910058621.4

文献号 : CN101499041B

文献日 :

基本信息:

PDF:

法律信息:

相似专利:

发明人 : 姜先刚邹渊蒋小青

申请人 : 成都优博创技术有限公司

摘要 :

本发明公开了一种避免主机在访问共享设备造成异常死锁的方法,主机为共享设备设置访问冲突标志,当低优先级任务访问共享设备,并循环查询共享设备操作完成标志是否被置1时,中断服务例程或高优先级任务打断低优先级任务并访问共享设备,在查询到共享设备操作完成标志被置1后,将其清0,并将访问冲突标志置1,随着中断返回或任务重新调度,低优先级任务继续执行,会检测到共享设备操作完成标志为0,但访问冲突标志为1,则退出循环查询(否则该任务进入死循环,造成死锁),重试访问共享设备。采用本发明的技术方案,可以避免上述死锁情况的发生,因方法简单可靠,特别适用于处理器性能不高,存储器资源紧张的嵌入式系统领域。

权利要求 :

1.一种避免主机在访问共享设备造成异常死锁的方法,适用于嵌入式系统,其特征在于,包括以下步骤:A、为所述共享设备设置一个访问冲突标志;

B、一个低优先级任务启动所述共享设备;

C、所述低优先级任务查询所述共享设备操作完成标志是否被置1,如果所述共享设备操作完成标志被置1,则转至步骤D,否则转至步骤E;

D、所述低优先级任务完成对所述共享设备访问,将所述共享设备操作完成标志清0,并结束流程;

E、所述低优先级任务查询所述共享设备访问冲突标志是否被置1,如果所述共享设备访问冲突标志被置1,则将其清0并转至步骤B,重试访问所述共享设备,否则转至步骤C;

F、当所述低优先级任务在执行步骤B、步骤C或者步骤E时,中断服务例程或高优先级任务打断了所述低优先级任务的执行并访问所述共享设备,则在所述中断服务例程或高优先级任务中启动共享设备,并转至步骤G;

G、所述中断服务例程或高优先级任务查询所述共享设备操作完成标志是否被置1,如果所述共享设备操作完成标志被置1,则转至步骤H,否则重新执行步骤G;

H、所述中断服务例程或高优先级任务将所述共享设备操作完成标志清0,共享设备访问冲突标志置1,并中断返回或任务重新调度,所述低优先级任务继续执行步骤B、步骤C或者步骤E。

2.根据权利要求1所述的方法,其特征在于,在访问共享设备的任务或中断服务例程中设置超时计数值,当所述任务或中断服务例程查询所述共享设备操作完成标志的次数超过所述超时计数值时,则退出查询循环,进行超时错误处理。

3.根据权利要求1所述的方法,其特征在于,在访问共享设备的低优先级任务中设置重试次数值,当所述低优先级任务访问所述共享设备的次数超过所述重试次数值时,进行访问冲突错误处理。

4.根据权利要求1至3中任一项权利要求所述的方法,其特征在于,所述共享设备是具有硬件标志反映操作已经完成的外围设备,包括嵌入式系统中的定时器、串口控制器、IIC总线控制器、SPI总线控制器、USB总线控制器、PWM控制器、比较器、模数转换器、数模转换器。

5.根据权利要求1至3中任一项权利要求所述的方法,其特征在于,所述嵌入式系统是前后台嵌入式系统,或者是具有操作系统的嵌入式系统。

说明书 :

技术领域

本发明涉及嵌入式系统技术领域,特别是涉及一种避免主机在访问共享设备造成异常死锁的方法。

背景技术

嵌入式处理器会连接各种外设来实现各种功能,虽然外设功能各不相同,但是嵌入式处理器同外设的握手方式通常只有两种,一种是查询方式,一种是中断方式。在使用了查询方式工作的系统中,可能会因为种种原因造成死锁,所以设计出可靠的软件保证系统不被死锁是相当重要的。
对于死锁,不同的领域会给出不同的定义,在这里主要是指嵌入式处理器一直在等待设备完成操作而不能做其它事情。死锁的必要条件归纳起来有下面几条:
1、互斥条件:一个资源每次只能被一个进程使用。
2、请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
3、不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
4、循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
在某些嵌入式系统软件中,上述“进程”可以理解为任务或某段访问共享资源的特定代码(在后面的描述中统称为任务)。随着软件技术的发展,解决共享资源访问冲突问题已经有很多种方法,比如禁止中断,利用互斥信号量和使用各种资源锁等等。但是这些方法都旨在解决怎样将共享资源合理分配给不同的任务使用,确保任务不会因为试图去获取某个共享资源而造成死锁。
而在嵌入式系统中,还有可能出现任务已经获取共享资源而死锁的现象。可能的原因是:
1、共享设备发生故障,则操作完成标志就可能不会被置位,对应的任务将一直处于等待状态而造成死锁。
2、当一个任务在查询共享设备操作完成标志是否被置1时,发生了一个中断或产生了任务调度,碰巧这个中断或者被调度执行的新任务也要访问这个共享设备,而中断服务例程或被调度的新任务在访问完共享设备后会清除共享设备操作完成标志(这是设备能够重新正常工作的必要条件),那么在中断返回后或任务被重新调度导致先前查询共享设备操作完成标志是否被置1的任务继续开始执行,去循环查询一个不可能再被置1的共享设备操作完成标志,则这个任务就被死锁。例如,一个任务需要采集某路模拟信号,在启动了模数转换器后,任务开始等待模数转换完成标志被置位,此时发生了一个中断或任务调度,碰巧在中断服务例程中或被调度的新任务中也要使用同样的模数转换器采集某路模拟信号,那么模数转换器将被重新启动,在转换结束后,转换完成标志被共享设备自动置1,中断例程或被调度的新任务检测到该标志被置位后清除该标志,然后执行其它操作,最终中断返回或者任务会被重新调度,而使先前等待模数转换完成标志置位的任务得到继续执行,但是此时模数转换器处于闲置状态,转换完成标志也就不会被置位了,那么该任务将永远等待下去造成死锁。这种情况比较隐蔽,在软件设计之初不易被考虑到。
综上所述,嵌入式系统的外设属于硬件资源,硬件发生故障可能会导致系统死锁;嵌入式系统的外设是互斥的,并且是不可剥夺的,其固有特性造成了死锁的必要条件;常规的方法只能解决共享资源分配问题,即只能解决资源分配前的问题,不能解决嵌入式系统中任务重新获得共享设备控制权后造成死锁的问题。

发明内容

本发明提供了一种避免主机在访问共享设备造成异常死锁的方法,能够解决任务在获取了共享设备控制权后发生死锁的问题。
为达到发明目的,本发明所采用的技术方案是:
一种避免主机在访问共享设备造成异常死锁的方法,适用于嵌入式系统,包括以下步骤:
A、为所述共享设备设置一个访问冲突标志;
B、一个低优先级任务启动所述共享设备;
C、所述低优先级任务查询所述共享设备操作完成标志是否被置1,如果所述共享设备操作完成标志被置1,则转至步骤D,否则转至步骤E;
D、所述低优先级任务完成对所述共享设备访问,将所述共享设备操作完成标志清0,并结束流程;
E、所述低优先级任务查询所述共享设备访问冲突标志是否被置1,如果所述共享设备访问冲突标志被置1,则将其清0并转至步骤B,重试访问所述共享设备,否则转至步骤C;
F、当所述低优先级任务在执行步骤B、步骤C或者步骤E时,中断服务例程或高优先级任务打断了所述低优先级任务的执行并访问所述共享设备,则在所述中断服务例程或高优先级任务中启动共享设备,并转至步骤G;
G、所述中断服务例程或高优先级任务查询所述共享设备操作完成标志是否被置1,如果所述共享设备操作完成标志被置1,则转至步骤H,否则重新执行步骤G;
H、所述中断服务例程或高优先级任务将所述共享设备操作完成标志清0,共享设备访问冲突标志置1,并中断返回或任务重新调度,所述低优先级任务继续执行步骤B、步骤C或者步骤E。
在访问共享设备的任务或中断服务例程中设置超时计数值,当所述任务或中断服务例程查询所述共享设备操作完成标志的次数超过所述超时计数值时,则退出查询循环,进行超时错误处理。
在访问共享设备的低优先级任务中设置重试次数值,当所述低优先级任务访问所述共享设备的次数超过所述重试次数值时,进行访问冲突错误处理。
所述共享设备是具有硬件标志反映操作已经完成的外围设备,包括嵌入式系统中的定时器、串口控制器、IIC总线控制器、SPI总线控制器、USB总线控制器、PWM控制器、比较器、模数转换器、数模转换器。
所述嵌入式系统是前后台嵌入式系统,或者是具有操作系统的嵌入式系统。
采用了本发明的技术方案,能够解决由于硬件或软件原因造成的访问共享设备造成任务死锁的问题,也能够解决任务在获取了共享设备控制权后发生死锁的问题,并且方法的实现简单、可靠,特别适用于处理器性能不高,存储器资源紧张的嵌入式系统领域。

附图说明

图1是本发明中避免访问共享设备造成死锁的流程图。
图2是本发明中针对前后台嵌入式系统中避免访问共享设备造成死锁的流程图。
图3是本发明中针对具有操作系统的嵌入式系统中避免访问共享设备造成死锁的流程图。

具体实施方式

下面结合附图和实施实例对本发明进一步说明。
图1是本发明中避免访问共享设备造成死锁的流程图。如图1所示,该流程包括以下步骤:
步骤101、在程序中为共享设备设置一个全局访问冲突标志。
步骤102、在低优先级任务中设置共享设备访问的重试次数值。
步骤103、在低优先级任务中启动共享设备并设置超时计数值。
步骤104、在低优先级任务中查询共享设备操作完成标志是否被置1,如果该标志被置1,则将其清0,并将共享设备访问冲突标志清0,表示所述低优先级任务对所述共享设备访问成功完成,可以执行低优先级任务中的其它操作,否则转至步骤105。
步骤105、在低优先级任务中检测超时计数值是否为0,如果为0,表示所述低优先级任务查询所述共享设备操作完成标志次数已经大于所规定的最多次数,所述低优先级任务应该进行相应的超时错误处理,否则转至步骤106。
步骤106、在低优先级任务中检测共享设备访问冲突标志是否被置1,如果没有被置1,则将超时计数值减1后转至步骤104,重新进入查询所述共享设备操作完成标志的循环,否则转至步骤107。
步骤107、在低优先级任务中检测所述共享设备访问重试次数值是否为0,如果为0,表明所述低优先级任务对所述共享设备的访问次数已经超过了所规定的最大次数,并且每次都发生了访问冲突(即所述低优先级任务在启动所述共享设备后到共享设备完成指定操作期间,有中断服务例程或高优先级任务打断了低优先级任务的执行,并访问了所述共享设备),则所述低优先级任务应该进行相应的访问冲突错误处理,并将所述共享设备访问冲突标志清0,否则将所述重试次数值减1,并将所述共享设备访问冲突标志清0,然后转至步骤103,进行重试访问共享设备的循环。
步骤108、在低优先级任务启动共享设备后到共享设备完成指定操作期间如果有中断服务例程或高优先级任务访问共享设备,所述低优先级任务被打断,从而转至步骤109,进入中断服务例程或高优先级任务的执行步骤中。
步骤109、在中断服务例程或高优先级任务中设置超时计数值,然后转至步骤110。
步骤110、在中断服务例程或高优先级任务中启动共享设备,然后转至步骤111。
步骤111、在中断服务例程或高优先级任务中查询共享设备操作完成标志是否被置1,如果该标志被置1,则转至步骤114,否则转至步骤112。
步骤112、在中断服务例程或高优先级任务中,检测超时计数值是否为0,如果为0,表示所述中断服务例程或高优先级任务查询所述共享设备操作完成标志次数已经大于所规定的最多次数,所述中断服务例程或高优先级任务应该进行相应的超时错误处理,转至步骤113,否则将超时计数值减1后,转至步骤111。
步骤113、在中断服务例程或高优先级任务中,进行共享设备访问超时错误处理,然后转至步骤114。
步骤114、在中断服务例程或高优先级任务中,将共享设备操作完成标志清0,并将共享设备访问冲突标志置1,然后执行中断服务例程或高优先级任务中的其它操作。
步骤115、随着中断返回或者任务的重新调度,先前被打断的低优先级任务将会继续从被打断处执行,即转至步骤104、步骤105、步骤106或步骤107,如前所述,低优先级任务将会检测到共享设备访问冲突标志被置1,从而进行共享设备访问的重试操作,而避免了死锁的发生。
在上述步骤的指导下,可以得出针对不同的嵌入式系统的具体实施方式。
下面描述一种前后台嵌入式系统中避免访问共享设备造成死锁的具体实施方式。在前后台嵌入式系统中,后台程序在任意时刻都可能被前台程序打断,所以后台程序属于可能失去共享设备控制权的代码(即所述避免访问共享设备造成死锁的流程步骤中的低优先级任务),在查询共享设备操作完成标志的同时需要检测共享设备访问冲突标志。前台程序属于具有抢占共享设备控制权能力的代码(即所述避免访问共享设备造成死锁的流程步骤中的中断服务例程),如果系统允许中断嵌套,并且有多个中断共享一个设备,那么,前台程序也属于可能失去共享设备控制权的代码(即所述避免访问共享设备造成死锁的流程步骤中的低优先级任务),所以前台程序需要在访问完共享设备后置位共享设备访问冲突标志,并根据实际情况确定是否需要在查询共享设备操作完成标志的同时检测共享设备访问冲突标志。
本具体实施方式考虑一种广泛的情况,在前后台嵌入式系统中,有一个后台程序和两个前台程序(前台程序1和前台程序2)共享一个设备,该系统允许中断嵌套,并且前台程序2的中断优先级高于前台程序1的中断优先级。
上述前后台嵌入式系统中的后台程序属于可能失去共享设备控制权的代码,前台程序1既属于可能失去共享设备控制权的代码又属于具有抢占共享设备控制权能力的代码,前台程序2属于具有抢占共享设备控制权能力的代码。下面分别给出各程序的C语言参考代码。
后台程序参考代码:
#define MaxLoopCycles 1000
#define MaxRetryCycles 2
unsigned char LootFlag;//①定义共享设备访问冲突标志,为一全局变量
void BackgroundXxx(void)
{
  unsigned int loop_count=MaxLoopCycles;
  unsigned char retry_count=MaxRetryCycles;
  while(retry_count)
  {
     StartDevice();//②启动设备,重试操作也要重新启动设备
     while(DCFlag==0&&LootFlag==0&&loop_count!=0)//③
查询设备操作完成标志DCFlag时
     {                       //同时检测访问冲突标志LootFlag和
        loop_count--;       //超时计数值loop_count
     }
     if(DCFlag!=0)//④设备操作完成标志被正常置位
     {
        DCFlag=0;//则将操作完成标志清零
        LootFlag=0;//将访问冲突标志清零
        break;//并退出重试循环
    }
    if(LootFlag!=0)//⑤如果发生了访问冲突,即在等待过程中被前
台程序打断
    {
        LootFlag=0;//则将访问标志清0
        retry_count--;//重试次数减1
        continue;//并进行重试
    }
    if(loop_count==0)//⑥如果访问超时
    {
        break;//则进行超时错误处理并退出重试循环
    }
  }
  if(retry_count==0)//⑦如果在规定的重试次数中,设备访问还是不
成功,则进行相应错误处理
  {
  }
  }
  前台程序1的参考代码:
  void ISR1Xxx(void)
  {
    unsigned int loop_count=MaxLoopCycles;
    unsigned char retry_count=MaxRetryCycles;
    while(retry_count)
    {
       StartDevice();//②启动设备,重试操作也要重新启动设备
    while(DCFlag==0&&LootFlag==0&&loop_count!=0)//③
查询设备操作完成标志DCFlag时
    {                    //同时检测访问标志LootFlag和
       loop_count--;    //超时计数值loop_count
    }
    if(DCFlag!=0)//④设备操作完成标志被正常置位
    {
       DCFlag=0;//则将标志清零
       LootFlag=1;//⑧与后台程序不同的是,在设备正常完成操作后
需要把访问冲突标志置位
       break;//并退出重试循环
    }
    if(LootFlag!=0)//⑤如果发生了访问冲突,即在等待过程中被前
台程序打断
    {
       LootFlag=0;//则将访问标志清0
       retry_count--;//重试次数减1
       continue;//并进行重试
    }
    if(loop_count==0)//⑥如果访问超时
    {
        break;//则进行超时错误处理并退出重试循环
    }
  }
  if(retry_count==0)//⑦如果在规定的重试次数中,设备访问还是不
成功,则进行相应错误处理
  {
  }
}
前台程序2的参考代码:
void ISR2Xxx(void)
{
  unsigned int loop_count=MaxLoopCycles;
  StartDevice();//①启动设备
  while(DCFlag==0&&loop_count!=0)//②查询设备操作完成标志
DCFlag时
  {                        //同时检测超时计数值loop_count
    loop_count--;
  }
  if(loop_count==0)//③如果访问超时,则进行超时错误处理并退出重
试循环
  {
  }
  DCFlag=0;//④设备操作完成标志置0
  LootFlag=1;//⑤访问标志置1
}
本具体实施方式可以避免即使在极端情况下发生死锁的现象。图2是本发明具体实施方式一在前后台嵌入式系统中避免访问共享设备造成死锁的流程图。如图2所示,在t0时刻,后台程序在启动共享设备后查询共享设备操作完成标志DCFlag是否被置1,共享设备访问冲突标志LootFlag是否被置1和超时计数值loop_count是否为0(后台程序注释③处)时发生了中断,该中断是前台程序1的中断,则前台程序1开始执行,此时共享设备操作完成标志DCFlag还未被置1,共享设备访问冲突标志LootFlag也为0。在t1时刻,前台程序1启动共享设备后查询共享设备操作完成标志DCFlag是否被置1,共享设备访问冲突标志LootFlag是否被置1和超时计数值loop_count是否为0(前台程序1注释③处)时又发生了中断,系统允许中断嵌套,并且该中断是前台程序2的中断,则前台程序2将开始执行,此时共享设备操作完成标志DCFlag也还未被置1,共享设备访问冲突标志LootFlag还是为0。之后前台程序2启动共享设备并顺利执行,在成功查询到设备操作完成标志DCFlag被置1后将其清0(前台程序2注释④处),并将共享设备访问冲突标志LootFlag置1(前台程序2注释⑤处),然后在t2时刻返回到前台程序1被中断的地方(前台程序1注释③处),如果此时共享设备访问冲突标志LootFlag没有被置1的话,那么由于共享设备操作完成标志DCFlag已经在前台程序2里面被清0,前台程序1将永远不会检测到共享设备操作完成标志DCFlag被置1,从而造成死锁。但是由于使用了本发明的方法,前台程序1检测到共享设备访问冲突标志LootFlag被置1,那么前台程序1将退出查询循环,并执行重试操作。假设在重试操作中没有被前台程序2中断,那么前台程序1将顺利执行,在执行完毕后将共享设备操作完成标志DCFlag清0(前台程序1注释④处),并将共享设备访问冲突标志LootFlag置1(前台程序1注释⑧处),然后在t3时刻返回至后台程序。同样的,如果后台程序没有检测共享设备访问冲突标志LootFlag,就会造成死锁。但是由于使用了本发明的方法,后台程序检测到共享设备访问冲突标志LootFlag被置1,那么后台程序将退出查询循环,并执行重试操作。假设在后台程序重试操作中没有发生中断,那么后台程序将会顺利执行,在成功查询到共享设备操作完成标志DCFlag被置1后将其清0,并将共享设备访问冲突标志清0,然后再执行其它操作,这样就避免了死锁的发生。
需要特别说明的是,超时计数值要根据具体情况设定,保证设备在正常完成操作的情况下,超时计数值不会减至0。另外,由于共享设备访问冲突标志LootFlag是一个全局变量,属于软件共享资源,如果系统不能保证对该标志的访问能在一条指令中执行完毕,那么需要使用额外的方法来访问该全局变量,比如使用互斥信号量等方法。
下面描述一种具有操作系统的嵌入式系统中解决死锁问题的具体实施方式。在有操作系统的嵌入式系统中,任务可能被新调度的任务打断,所以任务既属于可能失去共享设备控制权的代码(即所述避免访问共享设备造成死锁的流程步骤中的低优先级任务)又属于具有抢占共享设备控制权能力的代码(即所述避免访问共享设备造成死锁的流程步骤中的高优先级任务),在任务查询共享设备操作完成标志是否被置1时,需要检测共享设备访问冲突标志,并在任务访问完共享设备后需要将共享设备访问冲突标志置1。
在有操作系统的嵌入式系统中,中断服务例程(此处的中断服务例程是特定系统中的中断服务例程,同所述避免访问共享设备造成死锁的流程步骤中的中断服务例程有所区别)同前后台嵌入式系统中的前台程序,需要在访问完共享设备后将共享设备访问冲突标志置1,并根据是否有嵌套的中断访问共享设备来确定是否需要在查询共享设备操作完成标志是否被置1的同时检测共享设备访问冲突标志。
本具体实施方式考虑一种广泛的情况,在有操作系统的嵌入式系统中,两个任务同一个中断服务例程共享一个设备,图3是本发明具体实施方式二在有操作系统的嵌入式系统中避免访问共享设备造成死锁的流程图。如图3所示,任务1和任务2既属于可能失去共享设备控制权的代码又属于具有抢占共享设备控制权能力的代码,中断服务例程属于具有抢占共享设备控制权能力的代码。那么任务1和任务2就和上述前台程序1的形式相同,而中断服务例程就和上述前台程序2的形式相同。此处就不再给出示例代码了。在发生访问冲突时,其处理流程和上述处理流程基本相似,唯一不同的是在中断服务例程执行完毕后,任务1可能先于任务2执行,此时由于共享设备访问冲突标志LootFlag被置1,所以任务1不会死锁,之后任务2也会因为共享设备访问冲突标志LootFlag被置1而不会死锁。
显然,本领域的技术人员可以对本发明进行各种改动和变型而不脱离本发明的精神和范围。这样,倘若本发明的这些修改和变型属于本发明权利要求及其等同技术的范围之内,则本发明也意图包含这些改动和变型在内。