Round Robin

將域名解析到IP地址的計算方法

Round Robin(中文翻譯為輪詢調度)是一種以輪詢的方式依次將一個域名解析到多個IP地址的調度不同伺服器的計算方法。

概要


術語循環/輪轉/輪替(英語:Round-robin)用於多種情況中,通常指將多個某物輪流用於某事,例如“逐戶派對”(round-robin-party)中所有參與者要挨家挨戶地拜訪每位參與者的住處並參加那裡的小型聚會。聯名信(round-robin letter)往往是指一大群下屬為批評其領導而寫的一封信,這種信一般只在簽名人數多到難於逐個回復后才會寄出。

起源


該術語來源於含義為“帶子”的法語詞ruban,久而被訛用並成為慣用語。在17、18世紀時法國農民希望以請願的方式抗議國王時,通常君主的反應是將請願書中最前面的兩至三人逮捕並處決,所以很自然地沒有人希望自己的名字被列在前面。為了對付這種專制的報復,人們在請願書底部把名字簽成一個圈(如同一條環狀的帶子),這樣就找不出打頭的人,於是只能對所有參與者進行同樣的懲罰。這個辦法後來也被英國皇家海軍的水手們使用過。

演演算法


輪詢排程演演算法的原理是每一次把來自使用者的請求輪詢分配給內部中的伺服器,從1開始,直到N(內部伺服器個數),然後重新開始循環。
演演算法的優點是其間接性,它無需記錄當前所有聯機的狀態,所以它是一種無狀態排程
輪詢排程演演算法流程:
假設有一組伺服器N台,S = {S1, S2, ..., Sn},一個指示變數i表示上一次選擇的伺服器ID。變數i被初始化為N-1。
在系統實現時,我們引入了一個額外條件,當伺服器的權值為零時,表示該伺服器不可用而不被調度。這樣做的目的是將伺服器切出服務(如屏蔽伺服器故障和系統維護),同時與其他加權演演算法保持一致。所以,演演算法要作相應的改動,它的演演算法流程如下:
輪詢調度演演算法流程:
假設有一組伺服器S = {S0, S1, …, Sn-1},一個指示變數i表示上一次選擇的
伺服器,W(Si)表示伺服器Si的權值。變數i被初始化為n-1,其中n > 0。
j = i;
do {
j = (j + 1) mod n;
if (W(Sj) > 0) {
i = j;
return Si;
}
} while (j != i);
return NULL;
輪詢調度演演算法假設所有伺服器處理性能均相同,不管伺服器的當前連接數和響應速度。該演演算法相對簡單,不適用於伺服器組中處理性能不一的情況,而且當請求服務時間變化比較大時,輪詢調度演演算法容易導致伺服器間的負載不平衡。
雖然Round-Robin DNS方法也是以輪詢調度的方式將一個域名解析到多個IP地址,但輪詢DNS方法的調度粒度是基於每個域名伺服器的,域名伺服器對域名解析的緩存會妨礙輪詢解析域名生效,這會導致伺服器間負載的嚴重不平衡。這裡,IPVS輪詢調度演演算法的粒度是基於每個連接的,同一用戶的不同連接都會被調度到不同的伺服器上,所以這種細粒度的輪詢調度要比DNS的輪詢調度優越很多。

作用


RTX51Tiny可以配置成使用 round-robin多任務。Round-robin容許quasi-parallel執行多任務。任務並不是連續執行的,而是分時間片執行的(可用的CPU時間被分成時間片,RTX51 Tiny把時間片分配給各個任務)。時間片的時間很短(以毫秒為單位),所以任務看起來像連續執行一樣。任務在分配給他的時間片內執行(除非放棄)。然後切換到下一個就緒的任務。這個時間片在RTX51 Tiny Configuration.配置文件中定義.
下面的例子是一個使用round-robin多任務的RTX51 Tiny的程序。這個程序中的兩個任務都是循環計數器。RTX51 Tiny執行稱為job0的任務0。這個函數創建了另一個任務job1。Job0執行完它的時間片后,RTX51 Tiny開始執行job1。Job1執行完它的時間片后,RTX51 Tiny又返回到job0開始執行。然後再切換到job1,如此循環。
int counter0;
int counter1;
void job0 (void) _task_ 0 {
os_create (1);
while (1) {
counter0++;
}
}
void job1 (void) _task_ 1 {
while (1) {
counter1++;
}
}
注意:除了一個任務的時片到時,也可以使用函數os_wait 或函數os_switch_task通知RTX51 Tiny可以切換到另一個任務。函數os_wait掛起當前任務直到特定的事件發生。在這期間任何其他的任務都可以執行。
Cooperative 任務切換??如果你禁止了round-robin多任務,你必須設計並執行你的任務從而讓他你們以cooperativ方式工作。特別地,你必須在每個任務的某個地方調用。這些函數告知RTX51 Tiny切換到另一任務。
函數os_wait 和函數os_switch_task的不同之處在於os_wait可以讓你的任務等待某一事件的發生,而函數os_switch_task直接切換到另一個準務就緒的任務。
空閑任務
當沒有任務需要運行時,RTX51 Tiny執行空閑任務。空閑任務只是一個簡單的無限循環,比如:
有些8051器件提供了空閑模式,通過持起任務的執行以降低功耗,直到出現中斷。在這種模式下,所有外圍設備包括中斷系統仍然在繼續工作。
RTX51 Tiny允許你在空閑任務中初始化空閑模式(沒有其他任務需要執行)。當RTX51 Tiny時鐘節拍中斷(或任何其他中斷)出現,微控制器恢復執行程序。空閑任務執行的代碼可以通過配置文件CONF_TNY.A51進行配置並使能
堆棧管理
RTX51 Tiny在8051的IDATA內存區為每個任務維持一個堆棧。當一個任務執行時,給他準備了最大可能需要地堆棧。當任務切換時,前一個任務的堆棧被壓棧並重定位,而把當前任務的堆棧被重定位並彈棧。STACK是堆棧的起始地址。在這個例子中,位於堆棧中的對像包括全局變數寄存器和位地止內存,剩下的內存用作任務堆棧。內存的頂端在配置文件中定義。

配置信息


RTX51 Tiny可以由根據用戶的應用來定製。
配置
RTX51 Tiny必須根據你的嵌入式應用來配置。所有地配置參數都在櫝置文件CONF_TNY.A51中,這個文件位於\KEIL\C51\RTXTINY2\文件夾中,文件中的櫝置選可以你做如下事情。
● 指定時鐘節拍中斷寄存器組
● 指定時鐘節拍間隔(多個8051機器周期)
● 指定在時鐘節拍中斷中執用的用戶代碼
● 指定round-robin溢出時間
● 使能禁能round-robin任務切換
● 指定你的應用程序包含了長時間的中斷
● 指定是否使用了code banking
● 定義RTX51 Tiny的棧頂
● 指令需要最小的堆棧空間
● 指定堆棧錯誤時執行代碼
● 定義空閑任務操作
● CONF_TNY.A51的默認配置包含在RTX51 Tiny的庫中。然而,要在就用中使用配置文件,必須把配置文件拷貝到你的工程文件夾並添加到工程中。

注意


如果在工程中不包括配置文件,默認的配置文件將會自動地包含到工程中。後事存在庫中的配置文件可能會對你的應用起到相反效果
硬體時鐘
以下參數指定了如何配置制RTX51 Tiny的配件時鐘
INT_REGBANK 指定製RTX51 Tiny時鐘中斷使用的寄存器組,默認的是寄存器組1
INT_CLOCK 指定時鐘產生中斷前的周期數據。這個值的範圍是1000~65535。較小的值產生中斷較快。這個值用來計算時鐘的重新裝載值(65536-INT_CLOCK)。預設值是10000。
HW_TIMER_CODE 是一個宏定義,它用來指定在制RTX51 Tiny時鐘節拍中斷中執的代碼。這個宏預設的設置是從中斷中返回(RETI)如:
HW_TIMER_CODE MACRO
; Empty Macro by default
RETI
ENDM
Round-robin
Round-robin切換是默認使能的,以下參數用來設定Round-robin切換的時間或禁能Round-robin切換
TIMESHARING 指定任務在進行Round-robin切換前執行的RTX51 Tiny時鐘節拍數。當這個值為0時禁止Round-robin切換。預設值是5個時鐘節拍。
長時間中斷
一般情況下,中斷服務程序(ISRs)都要求很快執行完畢。有時候,中斷服務程序可能需執行很長一段時間。如果一個高優先順序的中斷執的時間超過了節拍間隔,RTX51的時鐘中斷就可能被這個更高優先順序的中斷中斷了,並且被以後的RTX51 時鐘中斷重入了。
如果使用了需要運行很長時間的高優先順序中斷,就應該考慮減少中斷服務程序的工作量,改變RTX51 時鐘節拍的速率,或考使用以下配置。
LONG_USR_ISR 指定是否使用執行時間超過時鐘節拍的中斷。當這個值置為1時,RTX51 Tiny就會把保護RTX51 Tiny時鐘節拍中斷重入的代碼包含進去。這個值預設為0
Code banking
以下設置指定RTX51 Tiny應用中是否使用code banking
CODE_BANKING 置1使用code banking,清0不使用code banking。預設值為0
注意:L51_BANK.A51的2.2或更高版本需要RTX51 Tiny 程序使用code banking
堆棧
堆棧的配置選項有幾個。以下參指定了用於堆棧的內存空間的大小和堆棧的最小空間。當CPU的堆棧空間不夠時用一個宏指定去執行哪一段代碼。
RAMTOP指定棧頂地址。最好不要修改這個地址除非你在這個堆棧的上面使用了IDATA變數。
FREE_STACK指定堆棧上的最少可用空間。當切換到一個任務是時,如果RTX51 Tiny檢測到可用的堆棧空間小於這個值,STACK_ERROR宏就會被執行。置為0將禁止對堆棧的檢查,預設值為20位元組
STACK_ERROR是一個宏,它代表了一段在堆棧出現錯誤時執行的代碼。這個宏的預設代碼為禁能中斷並進入一個無限循環。如
STACK_ERROR MACRO
CLR EA ; disable interrupts
SJMP $ ; endless loop if stack space is exhausted
ENDM
空閑任務
沒有任務需要執行時,RTX51 Tiny就執行空閑任務。空閑任務什麼都不做,只是等待RTX51 Tiny的時鐘節拍中斷並切換到另一個就緒的任務。以下參數用來配置RTX51 Tiny空閑任務的不同方面
CPU_IDLE 這是一個宏,代表了在空閑任務中執行的代碼。預設指令是設置寄存器PCON的空閑模式位。這樣就可以通過掛起程序節省能耗。如
CPU_IDLE MACRO
ORL PCON,#1 ; set 8051 CPU to IDLE
ENDM
CPU_IDLE_CODE 指定CPU_IDLE宏在空閑任務中是否執行。預設值為0,這樣空閑任務將不包含CPU_IDLE宏
庫文件
RTX51 Tiny包括兩個庫文件
RTX51TNY.LIB is used for non-banking RTX51 Tiny programs
RTX51BT.LIB is used for code-banking RTX51 Tiny programs.
The RTXTINY2.PRJ project found in the \KEIL\C51\RTXTINY2\SOURCECODE\ folder is used to build these two libraries.
注意:不需要在應用顯式地包含這兩個文件。如果你使用μVision2 IDE或command-line linker時這兩個文件會自動地包含進去。
如果要建立RTX51 Tiny的庫,預設的配置文件會加入進去。如果不顯式地聲明包含配置文件,默認的配置文件會包含進去。以後對配置文件做的修改會對就用產生意想不到的效果。
優化
可以通過以下方式優化RTX51 Tiny程序
如果可能,禁能round-robin任務切換。Round-robin需要13位元組堆棧空間來存儲任務地址和所有寄存器。如果任務切換是通過RTX51 Tiny運行時庫(比如os_wait或 os_switch_task)來觸發的就不需要這些空間了。
使用os_wait而不是使用round-robin的時間耗盡來切換任務。這些會提高系統的反應時間和任務的反應速度
避免把系統時鐘節拍的中斷速率設的太高。把時鐘溢出的時間設的比較短增加了每秒的時鐘節拍數但是減少了每個任的可用時間,因為每個時鐘節拍中斷會使用100-200個周期來運行。所以要把湔出時間設的足夠的小從而減小時鐘節拍中斷帶來的副作用。
使用RTX51 Tiny
要使用RTX51 Tiny,必須成功地生成RTX51程序並編譯連接他們
編寫程序
定義RTX51程序使用關鍵字 _task_
以RTX51TNY.H的模板使用RTX51 Tiny的內核
包含文件
RTX51 Tiny只需包含一個文件RTX51TNY.H。所有的運行時庫來常量都在這個頭文件中定義。可以採用以下方式包含它:
#include
編程指南
使用RTX51 Tiny編程時須遵循下規則:
包含文件rtx51tny.h
不要創建C主函數,RTX51 Tiny有它自已的主要函數
程序至少創建一個任務
程序必須至少調用一次RTX51 Tiny運行時庫(如os_wait)。否則,連接器將不會把RTX51 Tiny庫包含進去
任務0是你的程序執行的第一任務。必須調用在任務0中調用os_create_task函數來運行其他任務
任務永不返回或退出。任務必須使用while(1)或類似的結構。使用os_delete_task函數可以掛起一個任務
必須在μVision2中或在連接編譯命令行中指定RTX51 Tiny
定義任務
實時或多任務應用由一個或多個完成特定功能的任務組成。RTX51 Tiny支持最多16個任務
任務必須是用_task_聲明的C函數,返回值和參數都必須是void類型的,如
void func (void) _task_ task_id
這裡
func is the name of the task function.
task_id is a task ID number from 0 to 15
以下例子定義了函數job0作為一個任務,任務編號為0。
void job0 (void) _task_ 0 {
while (1) {
counter0++;
}
}
注意:所有的任務都必須通過循環實現,而且永不返回