作業系統導論第10章 多處理器排程(高階)

2021-10-09 14:43:04 字數 1568 閱讀 2037

前置知識:併發

考慮到快取完成了所有工作以提供一致性,程式(或os本身)在訪問共享資料時是否需要擔心一些事情?不幸的是,答案是肯定的。

當跨cpu訪問(特別是更新)共享資料項或結構時,應該使用互斥原語(例如鎖)來保證正確性(其他方法(例如構建無鎖資料結構)很複雜,只能偶爾使用)。

例如,假設有乙個共享佇列同時在多個cpu上被訪問。沒有鎖,即使使用基礎一致性協議,併發新增或刪除佇列中的元素也無法按預期工作。需要鎖以原子方式將資料結構更新為新狀態。

為了更加具體,請想象一下下面的**,該**用於從共享鍊錶中刪除元素,如圖所示。想象一下兩個cpu上的執行緒同時進入該例程。如果執行緒1執行第一行,它將在其tmp變數中儲存head的當前值;如果執行緒2然後也執行第一行,則它還將具有相同的head值儲存在其自己的私有tmp變數中(tmp分配在堆疊上,因此每個執行緒將擁有自己的私有空間)。因此,不是每個執行緒都從列表的開頭刪除元素,而是每個執行緒都將嘗試刪除列表中的同一頭元素,導致各種問題(例如,嘗試在第4行將head元素雙重釋放,以及可能兩次返回相同的資料值)。

typedef

struct __node_t node_t;

intlist_pop()

解決方案當然是通過鎖定使這些例程正確。在這種情況下,分配乙個簡單的互斥鎖(例如pthread_mutex_tm;),然後在例程的開頭新增乙個lock(&m)並在例程的末尾新增乙個unlock(&m)將解決此問題,確保**將如期執行。不幸的是,正如我們將看到的那樣,這種方法並非沒有問題,特別是在效能方面。具體來說,隨著cpu數量的增加,對同步共享資料結構的訪問變得非常緩慢。

在有了這一背景知識之後,我們現在討論如何為多處理器系統構建排程程式。最基本的方法是通過將所有需要排程的作業放入單個佇列中,從而簡單地將基本框架重用於單處理器排程。我們簡稱為單佇列多處理器排程sqms。這種方法具有簡單的優點。採取現有策略選擇下乙個要執行的最佳任務並使其適應於乙個以上cpu的工作並不需要太多工作(例如,如果有兩個cpu,它可以選擇執行兩個的最佳任務)。

但是,sqms有明顯的缺點。第乙個問題是缺乏可伸縮性。為了確保排程程式可以在多個cpu上正常工作,開發人員將在**中插入某種形式的鎖定,如上所述。鎖確保當sqms**訪問單佇列(例如,找到要執行的下乙個任務)時,會產生正確的結果。

不幸的是,鎖會極大地降低效能,尤其是隨著系統中cpu數量的增長。隨著對單個鎖爭用的增加,系統在鎖開銷上花費了越來越多的時間,而花費在系統應做的工作上的時間卻減少了。

sqms的第二個主要問題是快取相似性。例如,假設我們有五個任務要執行(a,b,c,d,e)和四個處理器。因此,我們的排程佇列如下所示:

隨著時間的流逝,假設每個任務執行乙個時間片,然後選擇另乙個作業,這裡是可能的乙個跨cpu的任務排程計畫:

作業系統(3) 多處理器程式設計 從入門到放棄

入門 理解多執行緒 三個放棄 原子性 有序性 可見性 程序與執行緒的區別 執行緒的建立 include include include void mythread void arg intmain int argc,char ar 執行結果 可以看到,執行緒建立後,可能立即執行,也可能處於就緒狀態,...

作業系統之執行緒 對稱多處理器和微核心 基礎知識

1.程序和執行緒 程序的概念包含兩個特點 分派的單元通常被稱作執行緒或輕量級程序,而擁有資料所有權的單位通常仍稱作程序或任務。多執行緒在多執行緒環境中,程序被定義成資源分派的單位和乙個被保護的單位,與程序相關聯的有 在乙個程序中,可能有乙個或多個執行緒,每個執行緒有 使用者級和核心級執行緒 2.對稱...

鎖 無鎖 多處理器程式設計 2 原子操作

原子操作是不可分割的操作,在執行完畢時它不會被任何事件中斷,原子操作是多數無鎖程式設計的基本前提。atomic是原子的意思,意味 不可分割 的整體。在linux kernel中有一類atomic操作api。這些操作對使用者而言是原子執行的,在乙個cpu上執行過程中,不會被其他cpu打斷。最常見的操作...