本文引自鏈接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並訪問臨界區和共享變量啊” 關 中 斷 之 后, 任 何 外 部 事 件 都 不 能 打 擾 處 理 機 連 續 執 行 臨 界 區 程 序。 如 果 臨 界 區 程 序 本 身 並 不 包 含 使 它 的 進 程 轉 變 為 封 鎖 狀 態 的 因 素, 那 么 這 種 方 法 就 能 保 證 臨 界 區 作 為 一 個 整 體 執 行。 這 種 方 法 的 優 點 是 簡 單、 可 靠, 但 是 它 也 有 一 定 的 局 限 性 和 若 干 不 足 之 處。 (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只在發生中斷時引起進程切換,這樣禁止中斷就能保證當前運行進程將臨界區代碼順利執行完,從而保證了互斥的正確實現。”顯然也是錯的。我們可以當作練習把它改正了。哈哈。