你的位置:首页 > 操作系统

[操作系统]关中断是否禁止任务调度?关中断能作为互斥吗?


      本文引自链接http://www.52rd.com/Blog/Detail_RD.Blog_imjacob_16830.html?WebShieldDRSessionVerify=COR6tnpfsOXExxEAO6Z6


今天再看《嵌入式软件系统教程》((美)西蒙 著,陈向群 等译)  ,里面讲到关中断会关了任务调度,作者没说原因,我也不知道为什么,所以查了查网络。

===============================================================
在这个网址http://www.hqwic.com/bbs/topic.aspx?topicid=11253上有一个讨论,我觉得很有道理。很明显观点是关了中断,只是禁止了抢占,但并没有禁止调度。
这样看来,那本书上的观点是不正确的??

把一些自认为很有道理的解释摘抄下来: 

 首先说明一下,引起调度(任务切换)的原因有两个:
1、任务主动进入了阻塞状态,就像2楼说的,调用了所谓的切换函数。
2、中断,中断服务程序(isr)改变了任务状态,使某个比当前任务优先级高的任务进入了准备好(ready)状态,于是内核调用了切换函数。

这两个原因可以称为“同步方式调度”和“异步方式调度”。抢占的意义在于:如果高优先级任务进入准备好状态后,操作系统可以立即调度(任务切换),将高优先级任务投入运行。而这些动作对低优先级任务来说是完全透明的。

但是,谁?!使高优先级任务进入准备好状态,而又对低优先级任务透明呢?就是“中断”。

所以说,“抢占”是系统进行了“异步方式调度”的结果。既然关闭了中断,也就禁止了抢占。楼主,你想明白了吗?

在这里也要纠正一下3楼和5楼:“关了中断,就禁止了调度”这种说法不妥。关了中断,只是禁止了抢占,但并没有禁止调度啊。

 

 正在运行的任务是所有就绪任务中优先级最高的,如果要运行其它优先级更高的任务,就只有发生了某些事件使得更高优先级的任务进入了就绪状态,而这些事件只有在两种情况下发生:
1. 中断改变了任务状态
2. 运行中的任务主动使优先级更高的任务进入就绪状态

2 相当于是主动放弃CPU占有权,所以说抢占是由中断引起的,是异步调度的结果(??这里逻辑有点问题。作者的意思可能是 :2是非抢占的,主动的,1是抢占的,被动的,所以说抢占是由中断引起的,是异步调度的结果。by imjacob)

所以就是你说的结论,关中断只是关了抢占,而运行中的任务依然可以主动做任务调度。这里uC/OS有一个非常重要的前提条件,就是 运行中的任务是所有就绪任务中优先级最高的,如果没有事件发生就会一直运行直到完成。

  

 所以,你最开始的疑问:“关中断只是屏蔽了中断,并没有阻止任务切换,高优先级的任务任然可以抢占CPU并访问临界区和共享变量啊”

关了中断,就禁止了抢占,如果当前任务也没有进行主动调度,当然系统中也就不会出现比当前优先级更高的任务进入就绪了,也就谈不上去“抢占CPU并访问临界区和共享变量”了。(作者这里说加了条件“如果当前任务也没有进行主动调度”,那如果当前任务进行了主动调度会怎么样?我认为,若是在临界区中进行了主动调度,那么后果就是提问的人说的:“关中断只是屏蔽了中断,并没有阻止任务切换,高优先级的任务任然可以抢占CPU并访问临界区和共享变量”。by imjacob)
由以下网址为证:http://www.gdjy.com.cn/xuexi/UNIX-XIUGAI/ch02/os0203.htm 中2.3.4为证。
上面是这么说的:

关 中 断 之 后, 任 何 外 部 事 件 都 不 能 打 扰 处 理 机 连 续 执 行 临 界 区 程 序。 如 果 临 界 区 程 序 本 身 并 不 包 含 使 它 的 进 程 转 变 为 封 锁 状 态 的 因 素, 那 么 这 种 方 法 就 能 保 证 临 界 区 作 为 一 个 整 体 执 行。 这 种 方 法 的 优 点 是 简 单、 可 靠, 但 是 它 也 有 一 定 的 局 限 性 和 若 干 不 足 之 处。

(1) 它 不 能 用 于 多 处 理 机 系 统。 其 原 因 是: 由 于 该 系 统 中 的 多 个 处 理 机 都 有 其 各 自 的 中 断 开 关, 因 此 一 个 处 理 机 并 不 能 阻 止 在 其 它 处 理 机 上 运 行 的 进 程 进 入 同 类 临 界 区。

(2) 在 临 界 区 中 如 果 包 含 有 使 执 行 它 的 进 程 有 可 能 进 入 封 锁 状 态 的 因 素, 则 也 不 能 使 用 这 种 方 法。 因 为 在 该 进 程 进 入 封 锁 状 态 后, 系 统 将 调 度 另 一 进 程 使 用 处 理 机, 如 果 需 要, 该 进 程 也 可 以 执 行 临 界 区 程 序, 不 会 受 到 任 何 阻 拦, 所 以 在 这 种 情 况 下, 开、 关 中 断 不 能 实 施 临 界 区 互 斥。

(3) 如 果 临 界 区 比 较 长, 则 本 法 会 降 低 中 断 响 应 速 度。

(4) 这 是 一 把 锁 处 理 各 类 临 界 区, 不 必 要 地 扩 大 了 互 斥 范 围。

  

 “为什么关中断开中断可以作为互斥条件,而且是最粗暴的方式呢?”

按上面的解释,开关中断是可以作为互斥条件的,但的确很粗暴。众所周知,嵌入式实时操作系统最关键的性能指标之一便是中断响应时间。中断响应时间越短,实时性就越好。但很多嵌入式操作系统(包括uCos在内)的中断响应时间都比较长。原因就是在这些操作系统中大量使用了关中断这种“粗暴”的方式(OS_ENTER_CRITICAL),你可以看看uCos, FreeRTOS等操作系统的源码,这样的写法比比皆是。当然,不用OS_ENTER_CRITICAL是不可能的,那会造成数据混乱,这是它们的系统结构所决定的。

如果能保证在中断处理中不去写共享数据(包括可能改变共享数据的系统调用),就可以不用关中断了,但这需要改变系统结构,把中断服务分为两个部分,这就是所谓的“Top half 和 Bottom half”。如果想了解具体,你可以去网上查查。应用这种技术的操作系统有Linux, Windows, eCos等。

  

 不用中断来进行调度的操作系统,就是没有抢占,说白了就是一个协作式操作系统,怎么会一定导致死锁?难道抢占式操作系统就不会出现死锁?

其实,死锁是多个任务在企图获取多个独占(exclusive)资源时,可能导致的一种所有参与任务全部被阻塞的状态。这分明是属于应用程序的逻辑概念,而调度则是属于操作系统的逻辑概念,怎么能混为一谈。


后记:

另外在查网络的时候,还看到一本中国人的书<操作系统教程>(http://books.google.cn/books?id=X8lmMtog0XcC&pg=PT59&lpg=PT59&dq=%E5%85%B3%E4%B8%AD%E6%96%AD+%E4%BA%92%E6%96%A5&source=bl&ots=GwX4qh0hM0&sig=j1ieBs1RvU-bTpkddC4OyxoneTc&hl=zh-CN&sa=X&oi=book_result&resnum=2&ct=result) 3.2.2 硬件方法中写:“ 因为cpu只在发生中断时引起进程切换,这样禁止中断就能保证当前运行进程将临界区代码顺利执行完,从而保证了互斥的正确实现。”显然也是错的。我们可以当作练习把它改正了。哈哈。


 
 
 
评 论
4楼 52RD网友 发表于 2008-11-27 12:29 回复
这是一个不浅也不深的问题,如果RTOS支持时间按片,那么与OS TIMER INT无法产生,基于时间片的调度就无法进行。 中断关了,CPU在公所,只有OS,你想想与这个有关吗?
3楼 JohnsonJin 发表于 2008-11-26 13:15 回复
所以,关中断不会禁止调度,还要在关中断处理的这个过程中不调用任何的OS函数,至少不能调用哪些会引起调度的函数。比如:资源申请,(内存申请,万一内存没有了呢),semaphore等同步函数的操作,给其他进程发消息....。
2楼 JohnsonJin 发表于 2008-11-26 13:11 回复
以上大部分都片面!我们先看调度发生的时机: 1. 中断 2. 系统调用。 然后我们看中断为什么会引起调度,通常中断会做一些处理,然后引起上层的“注意”。上层包括进程和负责进程调度的OS。如果系统支持时间片调度,那时钟中断引起OS把时间片到期的任务试着切换出去(如果没有相同优先级的进程在等待CPU的话,就不切换)。如果中断处理所需要引起的上层注意者是进程(中断ISR给进程发消息,信号,释放semaphore等),也就是本来在等待事件的进程被放到了ready队列。在中断处理结束的时候,OS的中断后处理过程会重新调度。这个时候就看谁的优先级高了,如果唤醒的是高优先级的进程,则做进程切换。系统调用其实也是一样的道理,在系统调用中,通常会引起资源或者锁的释放,或者触发其他高优先级进程ready,在系统调用结束的一刻,OS会重新尝试调度。