先看四個宏定義,進程和線程(線程就是任務)最高和最低優先級定義,[0,31]區間,即32級,優先級用于調度,CPU根據這個來決定先運行哪個進程和任務。
#define OS_PROCESS_PRIORITY_HIGHEST 0 //進程最高優先級 #define OS_PROCESS_PRIORITY_LOWEST 31 //進程最低優先級 #define OS_TASK_PRIORITY_HIGHEST 0 //任務最高優先級,軟時鐘任務就是最高級任務,見于 OsSwtmrTaskCreate #define OS_TASK_PRIORITY_LOWEST 31 //任務最低優先級
為何進程和線程都是32個優先級?
回答這個問題之前,先回答另一個問題,為什么人類幾乎所有的文明都是用十進制的計數方式。答案掰手指就知道了,因為人有十根手指頭。瑪雅人的二十進制那是把腳指頭算上了,但其實也算是十進制的表示。
這是否說明一個問題,認知受環境的影響,方向是怎么簡單/方便怎么來。這也可以解釋為什么人類語言發音包括各種方言對媽媽這個詞都很類似,因為嬰兒說mama是最容易的。注意認識這點很重要!
而計算機的世界是二進制的,是是非非,清清楚楚,特別的簡單,二進制已經最簡單了,到底啦,不可能有更簡單的了。還記得雙向鏈表篇中說過的嗎,因為簡單所以才不簡單啊,大道若簡,計算機就靠著這01碼,表述萬千世界。
但人類的大腦不擅長存儲,二進制太長了數到100就撐爆了大腦,記不住,為了記憶和運算方便,編程常用靠近10進制的 16進制來表示 ,0x9527ABCD看著比 0011000111100101010100111舒服多了。
應用開發和內核開發有哪些區別?
區別還是很大的,這里只說一點,就是對位的控制能力,內核會出現大量的按位運算(&,|,~,^) , 一個變量的不同位表達不同的含義,但這在應用程序員那是很少看到的,他們用的更多的是邏輯運算(&&,||,!)
#define OS_TASK_STATUS_INIT 0x0001U //初始化狀態 #define OS_TASK_STATUS_READY 0x0002U //就緒狀態的任務都將插入就緒隊列 #define OS_TASK_STATUS_RUNNING 0x0004U //運行狀態 #define OS_TASK_STATUS_SUSPEND 0x0008U //掛起狀態 #define OS_TASK_STATUS_PEND 0x0010U //阻塞狀態
這是任務各種狀態(注者后續將比如成貼標簽)表述,將它們還原成二進制就是:
0000000000000001 =0x0001U
0000000000000010 =0x0002U
0000000000000100 =0x0004U
0000000000001000 =0x0008U
0000000000010000 =0x0010U
發現二進制這邊的區別沒有,用每一位來表示一種不同的狀態,1表示是,0表示不是。
這樣的好處有兩點:
1.可以多種標簽同時存在比如 0x07 = 0b00000111,對應以上就是任務有三個標簽(初始,就緒,和運行),進程和線程在運行期間是允許多種標簽同時存在的。
2.節省了空間,一個變量就搞定了,如果是應用程序員要實現這三個標簽同時存在,習慣上要定義三個變量的,因為你的排他性顆粒度是一個變量而不是一個位。
而對位的管理/運算就需要有個專門的管理器:位圖管理器 (見源碼 los_bitmap.c )
什么是位圖管理器?
直接上部分代碼,代碼關鍵地方都加了中文注釋,簡單說就是對位的各種操作,比如如何在某個位上設1?如何找到最高位為1的是哪個位置?這些函數都是有大用途的。
//對狀態字的某一標志位進行置1操作
VOID LOS_BitmapSet(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap |= 1U << (pos & OS_BITMAP_MASK);//在對應位上置1
}
//對狀態字的某一標志位進行清0操作
VOID LOS_BitmapClr(UINT32 *bitmap, UINT16 pos)
{
if (bitmap == NULL) {
return;
}
*bitmap &= ~(1U << (pos & OS_BITMAP_MASK));//在對應位上置0
}
/********************************************************
雜項算術指令
CLZ 用于計算操作數最高端0的個數,這條指令主要用于一下兩個場合
計算操作數規范化(使其最高位為1)時需要左移的位數
確定一個優先級掩碼中最高優先級
********************************************************/
//獲取狀態字中為1的最高位 例如: 00110110 返回 5
UINT16 LOS_HighBitGet(UINT32 bitmap)
{
if (bitmap == 0) {
return LOS_INVALID_BIT_INDEX;
}
return (OS_BITMAP_MASK - CLZ(bitmap));
}
//獲取狀態字中為1的最低位, 例如: 00110110 返回 2
UINT16 LOS_LowBitGet(UINT32 bitmap)
{
if (bitmap == 0) {
return LOS_INVALID_BIT_INDEX;
}
return CTZ(bitmap);//
}
位圖在哪些地方應用?
內核很多模塊在使用位圖,這里只說進程和線程模塊,還記得開始的問題嗎,為何進程和線程都是32個優先級?因為他們的優先級是由位圖管理的,管理一個UINT32的變量,所以是32級,一個位一個級別,最高位優先級最低。
UINT32 priBitMap; /**< BitMap for recording the change of task priority, //任務在執行過程中優先級會經常變化,這個變量用來記錄所有曾經變化 the priority can not be greater than 31 */ //過的優先級,例如 ..01001011 曾經有過 0,1,3,6 優先級
這是任務控制塊中對調度優先級位圖的定義,注意一個任務的優先級在運行過程中可不是一成不變的,內核會根據運行情況而改變它的,這個變量是用來保存這個任務曾經有過的所有優先級歷史記錄。
比如 任務A的優先級位圖是 00000001001011 ,可以看出它曾經有過四個調度等級記錄,那如果想知道優先級最低的記錄是多少時怎么辦呢?
誒,上面的位圖管理器函數UINT16 LOS_HighBitGet(UINT32 bitmap)就很有用啦 ,它返回的是1在高位出現的位置,可以數一下是 6
因為任務的優先級0最大,所以最終的意思就是A任務曾經有過的最低優先級是6
一定要理解位圖的操作,內核中大量存在這類代碼,尤其到了匯編層,對寄存器的操作大量的出現。
比如以下這段匯編代碼。
MSR CPSR_c, #(CPSR_INT_DISABLE | CPSR_SVC_MODE) @禁止中斷并切到管理模式 LDRH R1, [R0, #4] @將存儲器地址為R0+4 的低16位數據讀入寄存器R1,并將R1的高16 位清零 ORR R1, #OS_TASK_STATUS_RUNNING @或指令 R1=R1|OS_TASK_STATUS_RUNNING STRH R1, [R0, #4] @將寄存器R1中的低16位寫入以R0+4為地址的存儲器中
編程實例
對數據實現位操作,本實例實現如下功能:
某一標志位置1。
獲取標志位為1的最高bit位。
某一標志位清0。
獲取標志位為1的最低bit位。
#include "los_bitmap.h" #include "los_printf.h" static UINT32 Bit_Sample(VOID) { UINT32 flag = 0x10101010; UINT16 pos; dprintf("\nBitmap Sample!\n"); dprintf("The flag is 0x%8x\n", flag); pos = 8; LOS_BitmapSet(&flag, pos); dprintf("LOS_BitmapSet:\t pos : %d, the flag is 0x%0+8x\n", pos, flag); pos = LOS_HighBitGet(flag); dprintf("LOS_HighBitGet:\t The highest one bit is %d, the flag is 0x%0+8x\n", pos, flag); LOS_BitmapClr(&flag, pos); dprintf("LOS_BitmapClr:\t pos : %d, the flag is 0x%0+8x\n", pos, flag); pos = LOS_LowBitGet(flag); dprintf("LOS_LowBitGet:\t The lowest one bit is %d, the flag is 0x%0+8x\n\n", pos, flag); return LOS_OK; }
結果驗證
Bitmap Sample! The flag is 0x10101010 LOS_BitmapSet: pos : 8, the flag is 0x10101110 LOS_HighBitGet:The highest one bit is 28, the flag is 0x10101110 LOS_BitmapClr: pos : 28, the flag is 0x00101110 LOS_LowBitGet: The lowest one bit is 4, the flag is 0x00101110
編輯:hfy
-
cpu
+關注
關注
68文章
10854瀏覽量
211585 -
鴻蒙系統
+關注
關注
183文章
2634瀏覽量
66308
發布評論請先 登錄
相關推薦
評論