8971|11

81

帖子

0

TA的资源

一粒金砂(初级)

楼主
 

关中断、开中断及其作用一问 [复制链接]

在嵌入式开发中,经常看到如下的代码(现在使用的是threadx):
TX_INTERRUPT_SAVE_AREA
……
TX_DISABLE
……
TX_ENABLE
尤其是在对硬件寄存器操作时基本上都要关中断。
我的理解是,关中断用来防止系统调度,保证对寄存器操作的原子性。但是如果仅仅是为了保证原子性,用信号量应该也可以,为什么非要用这么强烈的手段呢?
另外,关中断的作用都有什么,或者是什么时候需要关中断,大家可以在这里讨论一下。

最新回复

谈谈中断机制: 1、cpu的中断管理和指令执行(运算器)是两套硬件,他们互相独立又有关联。 2、无论中断是否允许,运算器都按自己的节奏工作,无须花时间去查询是否由中断到达。 3、中断管理器则不断地探测是否有中断信号到达,若有且中断允许,则保存当前执行状态信息,然后打断当前取指序列,强行转到特定地址(中断向量)取指令,整个过程运算器并不知道,它只是忠实地执行取指电路取得的指令。     因此,只要没有中断信号到达,就不存在cpu边走边看的问题。     为保证正确访问临界数据区和正确执行临界代码段,操作系统一般有:关中断、关调度、信号量,还有些操作系统提供原子变量的方法,linux中广为人知的锁其实是用信号量实现的。那么,这么多的方法中,什么情况适用哪一种方法呢?是有规律的。 1、原子变量     原子变量可以保证一个变量单次操作的正确性,其保护甚至比信号量还完善,信号量只能保护全局数据不被其他线程破坏,而原子变量能保证全局数据不被中断破坏。         example1:     atomic int a;         int b,c;         a = a + b + c;         上述代码中,cpu对a有一个读、修改、写的过程,这个过程如果被打断,并在其他线程中修改了a值,执行结果将出现错误,而原子变量将保证不会发生这样的错误。         原子变量不能保护一系列操作的原子性,若把上述代码改为         example2:         atomic int a;         int b,c;         a = a + b;                //L1         a = a + c;                //L2         原子变量不能保证L1和L2两行程序间a不被其他线程修改,因此example2不一定能得到正确的结果。 2、信号量     稍微完善一点的操作系统都提供信号量机制,用于保护临界代码。上述example2就应该用下列代码替代L1和L2:         获取信号量;         a = a + b;                //L1         a = a + c;                //L2         释放信号量;         当一个全局变量可能被多个线程操作时,就应该用信号量保护,注意,不能在中断中访问用信号量保护的变量。 3、关调度     关调度是一种比较粗暴的方式,关调度后,操作系统不会再进行线程上下文切换,而是专心执行一个线程,但是中断仍然开着。关调度可以起到替代信号量保护全局变量的作用,但一般不这样用,太粗暴了。但是如果某一段代码的执行时间有要求,希望cpu全速执行不被打断,但又不希望关中断时,可用关调度的方法。注意,从逻辑上,关调度能替换信号量,但不能替换原子变量。 4、关中断     关中断是最粗暴的一种方式,用于保证最严格的时序执行,比如某段代码要在IO上输出两个高精度脉冲,脉冲宽度2uS,间隔2uS,这种需求只能通过用精确的指令延时来实现,延时过程中,如果被中断,或者发生线程切换,将不能正确输出脉冲。从逻辑上,前面所讲的三种保护,都可以用关中断实现,只是,太粗暴了,软件不相信暴力!           详情 回复 发表于 2007-11-6 12:49
点赞 关注

回复
举报

73

帖子

0

TA的资源

一粒金砂(初级)

沙发
 
信号量如何能避免系统操作呢?除非是你写的系统.
 
 

回复

88

帖子

0

TA的资源

一粒金砂(初级)

板凳
 
这个跟通用寄存器有关,在中断和应用程序里都要用到通用寄存器,比如51中是A寄存器,ARM中是R0寄存器(当然ARM中有特殊的保护不同的系统状态他会调用不同的通用寄存器),这些寄存器在你的用户程序中会用到,在你的中断程序中也会用到,你在用C语言写程序的时候是看不出他们被调用的,所以在关键代码处要关闭中断,防止你的通用寄存器被中断修改。
 
 
 

回复

73

帖子

0

TA的资源

一粒金砂(初级)

4
 
尤其是在对硬件寄存器操作时基本上都要关中断。
我的理解是,关中断用来防止系统调度,保证对寄存器操作的原子性。但是如果仅仅是为了保证原子性,用信号量应该也可以,为什么非要用这么强烈的手段呢?
另外,关中断的作用都有什么,或者是什么时候需要关中断,大家可以在这里讨论一下。

To:
  1:是未了达到“干净”的原子性。
  2:用信号量,比喻使用互斥锁则能保证原子性,但效率不高,因为中断查询依然存在,
     并且中断服务函数会依然进来,只是你使用了信号量,使之阻塞了,有可能多次阻塞。
  3:关闭中断,可以重新修改中断服务,使之以新的姿态加入到中断表中。


 
 
 

回复

80

帖子

0

TA的资源

一粒金砂(初级)

5
 
谢谢各位,我的最新理解:
1 把这些寄存器理解为全局变量,如果这些寄存器在中断程序里也会被用到,就有必要在对这些寄存器操作时关中断,保证原子性;
2 对寄存器操作一般是在驱动程序里,驱动程序经常需要同时设置几个寄存器的值,如果在设置到一半时被中断,或者被其他任务中断,则会造成硬件状态的混乱。所以要关中断保证严格的原子性。

但是还有一个疑问,在嵌入式系统里面开关中断可能很平常,但是在linux或者windows里面开关中断应该是一件很重大的事情,应该极力避免的。记得linux driver development里面说过,几乎没有很说得过去的理由去关掉中断。所以很纳闷,在linux或者windows里面是怎么处理这样的情形的?
 
 
 

回复

66

帖子

0

TA的资源

一粒金砂(初级)

6
 
开关中断在实时操作系统中常用,常常是为了保证实时性.windows,linux都不是.

 
 
 

回复

62

帖子

0

TA的资源

一粒金砂(初级)

7
 
嵌入式系统往往是实时系统,实时系统的正确性来自于两个方面,一是逻辑正确性,二是准时性和及时性。
1、计算结果逻辑上的正确性并不需要关中断来保证,信号量足矣,任何正确的操作系统都会保证被信号量保护的数据,不必担心,所以有“linux   driver   development里面说过,几乎没有很说得过去的理由去关掉中断。所以很纳闷,在linux或者windows里面是怎么处理这样的情形的”,故无需为linux和windows感到纳闷,其他cpu也是一样。
2、准时性却不同,它要求在确定的时间得到正确的结果,什么时候会发生中断,中断服务要执行多长时间,是不可预测的,如果不关中断的话,计算机完成计算的时间将不可预测,结果是“你赶到了机场,但误了点”。有许多硬件信号需要按照严格的时序发出,操作这些硬件寄存器时如果不关中断,如何保证严格的时序?
 
 
 

回复

63

帖子

0

TA的资源

一粒金砂(初级)

8
 
to:zhangzhenbo:
2:用信号量,比喻使用互斥锁则能保证原子性,但效率不高,因为中断查询依
你说的中断查询依然存在是否是指:cpu执行完每条指令后依然会查询中断状态?如果关中断了,是不是cpu根本就不会查询中断状态,而是连续执行指令,而中间不查询中断状态?

不知道我的理解对不对?
 
 
 

回复

82

帖子

0

TA的资源

一粒金砂(初级)

9
 
关中断

感觉形像一点就是说:
某些时候CPU应该专心地做事,才能把那事做好...
 
 
 

回复

77

帖子

0

TA的资源

一粒金砂(初级)

10
 
临界段代码就需要保护其运行过程不被中断打断,以免造成数据破坏等等,这个时候就先关中断,然后等其执行完毕再开中断,注意这段代码必须很简单,具体ucos里面讲解的很详细,邵贝贝翻译的那本里面。


信号量之类一般是任务之间防止读脏之类出现才应用的,比如访问同一个打印机,用个信号量的话保证只有一个任务去操作。
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

11
 
lbing7 说的好~

感觉形像一点就是说:
某些时候CPU应该专心地做事,才能把那事做好...
 
 
 

回复

68

帖子

0

TA的资源

一粒金砂(初级)

12
 
谈谈中断机制:
1、cpu的中断管理和指令执行(运算器)是两套硬件,他们互相独立又有关联。
2、无论中断是否允许,运算器都按自己的节奏工作,无须花时间去查询是否由中断到达。
3、中断管理器则不断地探测是否有中断信号到达,若有且中断允许,则保存当前执行状态信息,然后打断当前取指序列,强行转到特定地址(中断向量)取指令,整个过程运算器并不知道,它只是忠实地执行取指电路取得的指令。
    因此,只要没有中断信号到达,就不存在cpu边走边看的问题。
    为保证正确访问临界数据区和正确执行临界代码段,操作系统一般有:关中断、关调度、信号量,还有些操作系统提供原子变量的方法,linux中广为人知的锁其实是用信号量实现的。那么,这么多的方法中,什么情况适用哪一种方法呢?是有规律的。
1、原子变量
    原子变量可以保证一个变量单次操作的正确性,其保护甚至比信号量还完善,信号量只能保护全局数据不被其他线程破坏,而原子变量能保证全局数据不被中断破坏。
        example1:
    atomic int a;
        int b,c;
        a = a + b + c;
        上述代码中,cpu对a有一个读、修改、写的过程,这个过程如果被打断,并在其他线程中修改了a值,执行结果将出现错误,而原子变量将保证不会发生这样的错误。
        原子变量不能保护一系列操作的原子性,若把上述代码改为
        example2:
        atomic int a;
        int b,c;
        a = a + b;                //L1
        a = a + c;                //L2
        原子变量不能保证L1和L2两行程序间a不被其他线程修改,因此example2不一定能得到正确的结果。
2、信号量
    稍微完善一点的操作系统都提供信号量机制,用于保护临界代码。上述example2就应该用下列代码替代L1和L2:
        获取信号量;
        a = a + b;                //L1
        a = a + c;                //L2
        释放信号量;
        当一个全局变量可能被多个线程操作时,就应该用信号量保护,注意,不能在中断中访问用信号量保护的变量。
3、关调度
    关调度是一种比较粗暴的方式,关调度后,操作系统不会再进行线程上下文切换,而是专心执行一个线程,但是中断仍然开着。关调度可以起到替代信号量保护全局变量的作用,但一般不这样用,太粗暴了。但是如果某一段代码的执行时间有要求,希望cpu全速执行不被打断,但又不希望关中断时,可用关调度的方法。注意,从逻辑上,关调度能替换信号量,但不能替换原子变量。
4、关中断
    关中断是最粗暴的一种方式,用于保证最严格的时序执行,比如某段代码要在IO上输出两个高精度脉冲,脉冲宽度2uS,间隔2uS,这种需求只能通过用精确的指令延时来实现,延时过程中,如果被中断,或者发生线程切换,将不能正确输出脉冲。从逻辑上,前面所讲的三种保护,都可以用关中断实现,只是,太粗暴了,软件不相信暴力!
       
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表