QNX 多核處理
俗話說,“三個臭皮匠,頂個諸葛亮”,這句話同樣適用於計算機系統,因爲在計算機系統中,兩個或多個處理器可以極大地提高性能。多處理系統可以採用以下形式:
- 離散或傳統:在板級總線上以多處理模式連接的獨立物理處理器的系統
- 多核心:一種芯片,它有一個物理處理器,多個cpu通過芯片級總線互連。多核處理器通過併發提供更強大的計算能力,提供更大的系統密度,並且比單處理器芯片運行的時鐘速度更低。多核處理器還減少了散熱、功耗和板面積(從而降低了系統的成本)。
多處理包括以下幾種工作模式: - 非對稱多處理(AMP) :一個獨立的操作系統或同一個操作系統的單獨實例化,運行在每個CPU上。
- 對稱多處理(SMP):一個操作系統的單一實例可以同時管理所有的cpu,並且應用程序可以浮動到其中的任何一個。
- 混合多處理(BMP):一個操作系統的單一實例同時管理所有的CPU,但是每個應用程序都被鎖定到一個特定的CPU。
Asymmetric multiprocessing (AMP)
非對稱多處理提供了與傳統單處理器系統類似的執行環境。它爲移植遺留代碼提供了一種相對簡單的路徑,併爲控制cpu的使用方式提供了一種直接的機制。在大多數情況下,它允許您使用標準的調試工具和技術。
AMP 能夠:
- 同構性——每個CPU運行相同類型相同版本的操作系統
- 非均勻性——每個CPU運行不同的操作系統或不同版本的相同的操作系統
QNX中微子的分佈式編程模型使您能夠充分利用同構環境中的多個cpu。在一個CPU上運行的應用程序可以與在其他CPU上運行的應用程序和系統服務(例如,設備驅動程序,協議棧)透明的通信,並且沒有傳統處理器間通信形式所帶來的高CPU佔用率。
在異構系統中,您必須實現一個專有的通信方案,或者選擇兩個共享公共基礎設施(可能是基於IP的)的操作系統來進行處理器間通信。爲了避免資源衝突,OSs還應該提供訪問共享硬件組件的標準化機制。
使用AMP,您可以決定應用程序使用的共享硬件資源如何在cpu之間分配。通常,這種資源分配在引導期間靜態發生,包括物理內存分配、外圍設備使用和中斷處理。雖然系統可以動態地分配資源,但是這樣做需要在cpu之間進行復雜的協調。
在AMP系統中,一個進程總是在同一個CPU上運行,即使其他CPU處於空閒狀態。結果,單個CPU可能會被過度使用或使用不足。爲了解決這個問題,系統可以允許應用程序動態地從CPU遷移到另一個CPU。但是,這樣做可能涉及複雜的狀態信息檢查點,或者當應用程序在一個CPU上停止而在另一個CPU上重新啓動時可能出現服務中斷。而且,如果cpu運行不同OS,這種遷移就算是可能的,但也是困難的。
Symmetric multiprocessing (SMP)
在多核設計中分配資源可能很困難,特別是當多個軟件組件不知道其他組件如何使用這些資源時。對稱多處理通過只運行QNX RTOS的一個副本在系統的所有CPU上,來解決這個問題。因爲操作系統在任何時候都能洞察所有的系統元素,所以它可以在多個cpu上分配資源,而很少或根本不需要應用程序設計人員的輸入。此外,QNX Neutrino提供了內置的標準化原語,如pthread_mutex_lock()、pthread_mutex_unlock()、pthread_spin_lock()和pthread_spin_unlock(),這些原語讓多個應用程序可以安全、輕鬆地共享這些資源。
通過只運行一個QNX中微子副本,SMP可以動態地將資源分配給特定的應用程序,而不是分配給cpu,從而更好地利用可用的處理能力。多處理系統作爲一個整體,它還允許系統跟蹤工具聚焦收集統計數據和應用程序交互,使您能夠深入瞭解如何優化和調試應用程序。
例如,IDE中的系統分析器可以跟蹤從一個CPU到另一個CPU的線程遷移,以及操作系統的基本原語、調度事件、應用程序到應用程序的消息傳遞和其他事件,所有這些都具有高精度的時間戳。由於使用標準的OS原語而不是複雜的IPC機制,應用程序同步也變得容易得多。
QNX中微子允許應用程序內的執行線程在任何CPU上併發運行,從而使整個芯片的計算能力始終對應用程序可用。QNX中微子的搶佔和線程優先級功能幫助您確保CPU週期到達最需要它們的應用程序。
QNX中微子RTOS的微核方法
SMP通常與高端操作系統相關聯,像Unix和widow NT 運行在高端服務器上一樣。這些大型的系統往往非常複雜,是許多人多年開發的結果。由於這些大型內核包含所有OS服務的大部分,因此支持SMP所需的更改非常廣,通常需要大量修改並在整個代碼中使用專門的自旋鎖。
另一方面,QNX微核包含一個非常小的微內核,內核周圍的進程充當資源管理器,提供文件系統、字符I/O和網絡等服務。通過單獨修改微內核,所有其他OS服務都可以充分利用SMP,而不需要修改代碼。如果這些提供服務的進程是多線程的,那麼它們的許多線程將被調度到可用的處理器中。甚至單線程服務器也將從中受益,因爲它的線程可以被調度在其他服務器和客戶端進程旁邊的可用處理器上。
作爲這種微內核方法的一個證明,啓用smp的QNX中微子內核/進程管理器只增加了幾kb的額外代碼。SMP版本是爲這些主要處理器家族設計的:
- ARM (procnto-smp)
- x86 (procnto-smp)
x86版本可以在任何符合Intel多處理器規範的系統上引導。QNX中微子還支持英特爾的超線程技術(在P4和Xeon處理器)。
procnt-smp管理器還可以在單個非smp系統上運行。由於構建一個雙處理器奔騰主板的成本與構建一個單處理器主板的成本非常接近,因此有可能通過簡單地添加第二個CPU來交付具有成本效益的解決方案。事實是操作系統本身只增加了幾千字節,使得SMP可以被認真考慮用於小型cpu密集型嵌入式系統,而不僅僅是高端服務器。
Booting an x86 SMP system
微內核本身只包含很少的特定於硬件或系統的代碼。確定系統功能的代碼被隔離在啓動程序中,啓動程序負責初始化系統、確定可用內存等。收集到的信息被放入微核和進程可用的內存表中(只讀)。
startup-bios程序被設計去兼容Intel MP規範(1.4版本及以後)。這個程序負責:
- 確定處理器的數量
- 確定本地和I/O APIC的地址
- 初始化每個附加的處理器
復位後,只有一個處理器將執行復位代碼。這個處理器稱爲引導處理器(BP)。對於找到的每個額外的處理器,運行startup-bios代碼的BP將:
- 初始化處理器
- 切換到32位保護模式
- 分配處理器自己的頁面目錄
- 設置處理器旋轉,禁用中斷,等待內核釋放
How the SMP microkernel works
一旦釋放並運行了額外的處理器,所有處理器都被視爲線程調度的對等點。
- Scheduling
調度策略遵循與單處理器系統相同的規則。也就是說,最高優先級的線程將在可用的處理器上運行。如果一個新線程已經準備好作爲系統中優先級最高的線程運行,那麼它將被分配給適當的處理器。如果選擇了多個處理器作爲潛在目標,那麼微內核將嘗試將線程分派到它最後運行的處理器。此關聯用於嘗試減少從一個處理器到另一個處理器的線程遷移,提高緩存性能。
在SMP系統中,調度器在確定如何調度其他線程方面具有一定的靈活性,其目的是優化緩存使用和最小化線程遷移。這可能意味着一些處理器將運行低優先級的線程,而高優先級的線程正在等待在它上次運行的處理器上運行。下一次,那個運行低優先級線程的處理器做調度決策時,它將選擇高優先級線程。在任何情況下,在單處理器系統上的實時調度規則在SMP系統上得到了保證。 - Kernel locking
在單處理器系統中,一次只允許一個線程在微內核中執行。大多數內核操作的持續時間都很短(通常在奔騰類處理器上只有幾微秒)。微內核還被設計成完全可搶佔的,並且對於那些需要更多時間的操作可以重新啓動。這種設計保持了微內核的精簡和快速,而不需要大量的細粒度鎖。令人關注的是,在通過內核的主代碼路徑中放置許多鎖將顯著降低內核的速度。每個鎖通常涉及處理器總線事務,這可能導致處理器停機。
在SMP系統中,QNX中微子總保持一個理念:只有一個線程可搶佔可重啓內核。微內核可以被任何處理器訪問,但是每次只允許一個處理器訪問。
對於大多數系統,花在微內核上的時間只佔處理器工作負載的一小部分。因此,當衝突發生時,它們應該是例外而不是常態。這對於微內核尤其正確,因爲微內核中,操作系統的服務是獨立進程,而不是內核本身的一部分。 - 處理器間中斷 Interprocessor interrupts (IPIs)
處理器之間通過IPIs(處理器間中斷)進行通信。IPIs可以在多個處理器上有效地調度和控制線程。例如,在以下情況下常常需要向另一個處理器發送IPI:
- 高優先級線程準備就緒
- 在另一個處理器上運行的線程被一個信號命中
- 在另一個處理器上運行的線程被取消
- 在另一個處理器上運行的線程被銷燬
Critical sections
爲了控制對它們之間共享的數據結構的訪問,線程和進程使用標準的POSIX原語的互斥、控制器和信號量。這些在SMP系統中無需更改即可工作。
許多實時系統還需要保護中斷處理程序和擁有該處理程序的線程之間對共享數據結構的訪問。中斷處理程序不能使用線程之間使用的傳統POSIX原語。這裏有兩個解決方案:
- 一種方法是從中斷處理程序中刪除所有的工作,取而代之的是在線程執行所有的工作。考慮到我們的快速線程調度,這是一個非常可行的解決方案。
- 在運行QNX中微子RTOS的單處理器系統中,中斷處理程序可能搶佔一個線程,但線程永遠不會搶佔中斷處理程序。這允許線程通過在非常短的時間內禁用和啓用中斷來保護自己不受中斷處理程序的影響。
非smp系統上的線程使用下面的代碼保護自己:
InterruptDisable()
// critical section
InterruptEnable()
Or:
InterruptMask(intr)
// critical section
InterruptUnmask(intr)
不幸的是,這段代碼在SMP系統上會失敗,因爲線程可能在一個處理器上運行,而中斷處理程序在另一個處理器上併發運行!一種解決方案是將線程鎖定到特定的處理器(BMP)。更好的解決方案是使用線程和中斷處理程序都可用的新排除鎖。這是由以下原語提供的,它們可以在單處理器和SMP機器上工作:
- InterruptLock(intrspin_t* spinlock )
嘗試獲取一個自旋鎖(這是中斷處理程序和線程共享的一個變量)。代碼將在一個緊密的循環中旋轉,直到獲得鎖爲止。禁用中斷之後,代碼將獲得鎖(假設被一個線程申請獲取)。鎖必須儘快打開(通常在幾行C代碼中,且沒有任何循環)。 - InterruptUnlock(intrspin_t* spinlock )
釋放鎖並重新啓用中斷
在非smp系統中,不需要自旋鎖。
Bound multiprocessing (BMP)
綁定多處理提供了非對稱多處理模型的調度控制,同時保留了對稱多處理的硬件抽象和管理。BMP類似於SMP,但是您可以指定一個線程可以在哪個處理器上運行。您可以在同一個系統上同時使用SMP和BMP,從而允許一些線程從一個處理器遷移到另一個處理器,而其他線程只能遷移到一個或多個處理器。
與SMP一樣,操作系統的單一副本維護所有系統資源的整體視圖,允許在應用程序之間動態分配和共享這些資源。但是,在應用程序初始化期間,系統設計人員確定的設置將強制應用程序的所有線程僅在指定的CPU上執行。與完全的浮動SMP操作相比,這種方法有以下幾個優點:
- 通過允許共享相同數據集的應用程序僅在相同的CPU上運行,它消除了SMP系統中可能降低性能的緩存抖動。
- 它提供了比SMP更簡單的應用程序調試,因爲應用程序中的所有執行線程都在一個CPU上運行。
- 它幫助使用糟糕的同步共享數據技術的遺留應用程序正確地運行(通過讓它們在單個CPU上運行)。
使用BMP,鎖定到一個CPU的應用程序不能使用其他CPU,即使它們是空閒的。但是,QNX中微子RTOS允許您動態地更改指定的RTOS CPU,無需檢查點,然後停止並重新啓動應用程序。
QNX中微子通過運行掩碼(runmask)支持硬處理器親和的概念。runmask中設置的每個位代表一個線程可以在其上運行的處理器。默認情況下,一個線程的runmask被設置爲所有的,允許它在任何處理器上運行。0x01的值將允許線程僅在第一個處理器上執行。
默認情況下,進程和線程的子類不繼承runmask;存在一個獨立的繼承mask。
通過謹慎地使用這些掩碼,系統設計人員可以進一步優化系統的運行時性能(例如,通過將非實時進程轉移到特定的處理器)。但是,通常不需要這樣做,因爲當高優先級線程準備就緒時,我們的實時調度器總是會立即搶佔一個低優先級線程。處理器鎖定可能只會影響緩存的效率,因爲可以防止線程遷移。
你可以指定一個新的線程或進程的運行掩碼: - 當你調用spawn()時,設置inheritance結構的runmask成員且指定SPAWN_EXPLICIT_CPU flag
- 當你launch一個程序時,用-C和-R 選項在on 工具上。這也將進程的繼承掩碼設置爲相同的值。
你可以改變一個現有的線程或進程的運行掩碼: - 在內核調用ThreadCtl()上使用使用_NTO_TCTL_RUNMASK或_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT。
- 使用-C或-R選項在slay 工具。如果您也加上-i選項,那麼slay將inherit mask設置爲相同的值。
可行的遷移策略
作爲AMP和SMP之間的中間點,BMP提供了一個可行的遷移策略,如果您希望遷移到完整的SMP,但是您擔心現有代碼可能在真正的併發執行模型中運行不正確。
您可以將遺留代碼移植到多核系統,並最初將其綁定到單個CPU,以確保正確的運行。通過明智地將應用程序(以及可能的單線程)綁定到特定的cpu,您可以將潛在的併發問題隔離到應用程序和線程級別。解決這些問題將允許應用程序完全併發運行,從而最大化多處理器提供的性能收益。
選擇AMP,SMP,和BMP
在AMP, SMP和BMP之間的選擇取決於你試圖解決的問題:
- AMP可以很好地與遺留應用程序一起工作,但是跨CPU的可伸縮性有限。
- SMP提供了透明的資源管理,但是那些沒有爲併發性做適當設計的軟件可能會有問題。
- BMP提供了許多與SMP相同的優點,但它保證了單處理器應用程序將正確地運行,極大地簡化了遺留軟件的遷移。
靈活選擇各個模型,需要平衡,性能,可擴展性,易遷移性,如下表展示:
Feature | SMP | BMP | AMP |
---|---|---|---|
資源無縫共享 | Yes | Yes | — |
跨雙CPU的擴展性 | Yes | Yes | Limited |
遺留程序的運行 | In most cases | Yes | Yes |
混合操作系統環境(e.g. QNX and Linux) | — | — | Yes |
功能性的專用處理器 | — | Yes | Yes |
多核間的消息收發 | 快(操作系統原語) | 快(操作系統原語) | 慢(app) |
CPU間線程同步 | YES | YES | — |
負載平衡 | YES | YES | — |
系統範圍的調試和優化 | YES | YES | — |