閱讀683 返回首頁    go 技術社區[雲棲]


vxWorks內核實現基本原理

 內核實現基本原理
    VxWorks 內核維護三個隊列:tick隊列、ready 隊列、active 隊列。另外還有一個隊列涉及任務,即任務等待資源時所處的隊列,這個隊列可以是VxWorks內核提供的,也可以是用戶提供的,此處令其為pend隊列。
    所謂tick 隊列,即當調用taskDelay 函數讓任務延遲一段固定的時間時,任務所處的隊列,此時任務被設置為Delay狀態,無資格競爭使用CPU;ready隊列即有資格競爭使用CPU的所有任務,該隊列以優先級為序排列任務,隊列頭部是除了當前運行任務外,係統中最高優先級的任務;active 隊列有些誤導,實際上稱之為task 隊列更合適,因為係統中所有的任務無論當前狀態如何,都將在這個隊列中,這個隊列維護著係統中當前所有的任務,即通過該隊列可以查找到當前係統中的所有任務,在Shell 下運行“i”命令,顯示係統中所有的任務,就是通過遍曆active隊列完成的;pend隊列即當任務競爭使用某資源,而資源當前不可得時,任務就被設置為pend狀態,進入pend隊列。
    函數taskSpawn 創建一個新的任務。首先,其創建一個任務控製結構,對該結構進行初始化後,將結構加入active隊列以作為係統任務管理之用。此時任務仍無資格競爭使用CPU,taskSpawn函數的最後一步就是將這個任務結構再加入到ready隊列,此時這個任務才真正可以稱為已經在競爭使用CPU了。當係統中所有的優先級高於這個任務的其他任務運行完畢或者由於等待資源而處於阻塞時,這個新創建的任務就將被調度運行。所以,在VxWorks下,如果一個新創建的任務優先級不高,創建後將等待一段時間才能被真正執行。在實際項目中,有時需要一個新的任務被創建後立刻得到執行,那麼就需要在創建任務時,指定一個較高的任務優先級。VxWorks 內核將任務分為256個優先級,標號從0到255。其中 0表示最高優先級,255表示最低優先級。任務在調用taskSpawn 函數進行創建時就指定了優先級,當然任務的優先級並非在創建後就無法改變,用戶可以通過調用taskPrioritySet函數在任務創建後重新設定優先級,taskPrioritySet專門針對嵌入式平台下不同的情況對同一任務不同運行級別的需求進行設置。值得注意的是,taskPrioritySet函數不同於通用操作係統提供的類似函數,taskPrioritySet函數可以提高或者降低任務的運行級別,而不是通用操作係統下在任務創建後就隻能動態地降低任務優先級。
    VxWorks 下對於應用層任務,推薦使用100~250 之間的優先級,驅動層任務可以使用51~99 之間的優先級。要特別注意的是,內核網絡數據包收發任務tNetTask的優先級為50,如果使用網口進行調試,則一定注意不要創建任務優先級高於50 的任務,否則tNetTask 任務將無法得到運行,表現形式是死機,因為係統將無法再從網口接收調試命令,無法響應Tornado Shell或者Telnet下輸入的任何命令。以上隻是推薦值,事實上,由於嵌入式係統下的特殊應用,對於某個任務優先級的設置需要根據該任務完成的具體工作而定,而不可一味地遵循推薦值。要謹記在任務達到某一特殊目的後,必須將任務優先級設置回正常(推薦)值。
    無論何種操作係統,任務在設計中都由一個數據結構表示。這個數據結構包含一個任務運行時需要的所有信息,我們一般將這些信息稱為任務上下文。具體的任務上下文(廣義上)包括以下內容:
    1)所在平台CPU 內部所有的寄存器值,特別是指令寄存器,這代表了任務當前的執行點。這一般是狹義上的任務上下文。除了寄存器值,每個任務有自己的內存映射空間、任務名稱、任務優先級值、任務入口函數地址、打開文件句柄數組、信號量和用於各種目的的隊列等。
    2)任務運行時暫時存放函數變量以及函數調用時被傳遞參數的棧。從操作係統底層實現來看,很多操作係統將表示任務的數據結構和任務棧統一管理,如Linux 下在分配任務結構的同時分配任務的內核棧,這兩者作為一個整體進行內存分配,通常將一頁(如4KB)的開始部分作為任務結構,用以存儲任務關鍵信息,而將頁的末尾作為任務內核棧的頂部。如此,實際上用一頁頁麵的大小(通常為4KB)減去任務信息占據的空間,剩下的空間都作為任務的內核棧在使用。VxWorks 與Linux 在棧的分配和管理上基本類似,不過VxWorks 區分於Linux 的一個最大不同是VxWorks 下所有的代碼都運行在一個狀態下,不區分內核態和用戶
態。VxWorks下的任務自始至終都在使用同一個棧,不論這個任務在運行過程中調用了任何VxWorks內核函數,都不存在棧的切換。正因如此,VxWorks對棧的大小無法預先進行把握,棧的大小將由被創建的任務決定,而且不同於通用操作係統,VxWorks下任務棧在任務創建時就被確定,而且此後不可以改變棧的大小。所以,對於一個存在很多遞歸調用的任務,必須在任務創建時指定一個較大的任務棧,防止在後續的運行中造成棧的溢出,導致任務異常退出。
    3)各種定時信息。這些信息實際上都作為任務結構中的一個字段而存在。任何操作係統都必須有一個係統時鍾進行驅動,該係統時鍾通常稱為係統的脈搏。係統時鍾一定與一個高優先級的中斷聯係,這樣,每當時鍾前進一個滴答(Tick),操作係統就會響應一次中斷,該中斷通常就被作為操作係統進程調度的觸發點。每次滴答,操作係統都會增加內核維護的一個全局變量(如VxWorks操作係統維護的vxTick變量),通過該變量為係統各種定時器提供定時依據。每個任務都有一個內部固定的定時器,用於任務內部特定的需求,每次係統時鍾產生一個中斷,操作係統都會對當前係統內所有需要關注的任務定時器進行處理,從而完成任務定時器特殊的用途。定時器的一個特殊變相應用即Round-Robin 任務調度(簡稱RR 調度)。RR 調度實際上對每個支持RR 調度的任務內部都維護有一個定時器。當一個支持RR調度的任務被調度進入運行狀態時,在任務運行期間,每次係統時鍾前進一個滴答時,該定時器指針都會前進一個單位。當到達預定的值時,該任務就要主動讓出CPU,以便讓相同優先級的其他任務運行。定時器可以以加法或者減法運算運行。對於減法運算,一般根據定時時間計算出一個Tick數,每次係統前進一個滴答,Tick數減一,當到達0 時,表示定時器到期。而對於加法運算,則一般需要使用操作係統維護的全局Tick變量。VxWorks下,如設置
定時時間間隔為N,則定時器到期時間為vxTick+N=T0,每次係統前進一個滴答,操作係統會對當前係統內維護的所有定時器進行檢查,判斷T0是否大於vxTick,一旦T0小於或等於vxTick,則表示該定時器到期,此時將根據定時器的目的做出相應的響應。
    4)信號處理函數。事實上,操作係統的每個信號都有一個默認的響應方式,如用戶在命令行       按“Ctrl+C”組合鍵時,則係統默認響應方式是中止當前前台任務。每個任務可以根據自身情況定製對某個信號的響應方式。如一個任務可以將用戶的“Ctrl+C”組合鍵操作響應為打印輸出當前任務中某個變量的值。每個任務內部對每個信號都維護一個響應函數句柄,操作係統在創建任務時已經將所有的句柄設置為係統默認方式,用戶在創建任務後,可以針對某個信號安裝自己的信號響應句柄。
    5)其他輔助信息。這些信息包括統計上的一些數據,如任務運行總時間、任務最終返回值等。
閱讀(1069) | 評論(0) | 轉發(5) |

最後更新:2017-04-03 12:55:36

  上一篇:go 基於嵌入式操作係統VxWorks的多任務並發程序設計(2) ――任務控製
  下一篇:go Android抽屜效果 DrawerLayout 入門經驗總結