版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、UCOS 時(shí)間片輪轉(zhuǎn)調(diào)度算法詳解2009年8月4日 1. UCOS 一種只支持優(yōu)先級(jí)搶占型調(diào)度的操作系統(tǒng)。它不支持同一個(gè)優(yōu)先級(jí)有 2 個(gè)及以上的任務(wù)同時(shí)運(yùn)作。 我修改的 UCOS 支持不同優(yōu)先級(jí)調(diào)度的同時(shí),支持同一個(gè)優(yōu)先級(jí)有 2 個(gè)以上的任務(wù)以時(shí)間片輪轉(zhuǎn)方式進(jìn)行調(diào)度。 這個(gè)就是 UCOS 和我修改的 UCOS 的區(qū)別。 我修改后的 UCOS,在以后的文段中就稱(chēng)為“FIFO-UCOS”。 FIFO 就是先進(jìn)先出的意思,和時(shí)間片輪轉(zhuǎn)調(diào)度差不多的意思。 一. FIFOUCOS核心思想 UCOS 在調(diào)度的時(shí)候,會(huì)按照優(yōu)先級(jí)選擇進(jìn)程進(jìn)行調(diào)度,我做的部分就僅僅是在他進(jìn)行優(yōu)先級(jí)檢查之前,把和運(yùn)行態(tài)同等級(jí)的進(jìn)
2、程進(jìn)行了替換,替換成了時(shí)間片輪轉(zhuǎn)調(diào)度的下一個(gè)進(jìn)程! 二.TCB 的修改 FIFO-UCOS 和 UCOS 并不能完全兼容,最大的改變,就是對(duì) TCB 的結(jié)構(gòu)做了改動(dòng),加入了我自己的段。 該部分代碼在 UCOS-II.H 文件中: typedef struct os_tcb OS_STK *OSTCBStkPtr; /* 當(dāng)前任務(wù)堆棧棧頂指針 */ #if OS_TASK_CREATE_EXT_EN 0 void *OSTCBExtPtr; /* 指向用戶(hù)定義的任務(wù)控制塊擴(kuò)展*/ OS_STK *OSTCBStkBottom; /* 指向任務(wù)堆棧棧底指針 */ INT32U OSTCBStkSi
3、ze; /*存有棧中可容納的指針元數(shù)目而不是用字節(jié)(Byte)表示的棧容量總數(shù)。*/ INT16U OSTCBOpt; /* Task options as passed by OSTaskCreateExt() */ INT16U OSTCBId; /* Task ID (0.65535) 存儲(chǔ)任務(wù)的識(shí)別碼ID,備用 */ #endif struct os_tcb *OSTCBNext; /*指向后一個(gè)任務(wù)控制塊的指針*/ struct os_tcb *OSTCBPrev; /*指向前一個(gè)任務(wù)控制塊的指針*/ #if (OS_Q_EN 0) & (OS_MAX_QS 0) | (OS_MBO
4、X_EN 0) | (OS_SEM_EN 0) | (OS_MUTEX_EN 0) /* OS_EVENT_EN定義為:能使隊(duì)列代碼產(chǎn)生&申請(qǐng)隊(duì)列控制塊最大數(shù)不為零|能使郵箱代碼產(chǎn)生| 能使信號(hào)量代碼產(chǎn)生|能使互斥量代碼產(chǎn)生 */ OS_EVENT *OSTCBEventPtr; /*指向事件控制塊的指針*/ #endif #if (OS_Q_EN 0) & (OS_MAX_QS 0) | (OS_MBOX_EN 0) void *OSTCBMsg; /* Message received from OSMboxPost() or OSQPost() 指向傳遞給任務(wù)的消息的指針*/ #endi
5、f #if (OS_VERSION = 251) & (OS_FLAG_EN 0) & (OS_MAX_FLAGS 0) #if OS_TASK_DEL_EN 0 /* OS版本大于等于251&能使事件標(biāo)志代碼產(chǎn)生&最大標(biāo)志數(shù)大于零*/ OS_FLAG_NODE *OSTCBFlagNode; /*指針指向事件標(biāo)志節(jié)點(diǎn)*/ #endif OS_FLAGS OSTCBFlagsRdy; /* Event flags that made task ready to run事件標(biāo)志使任務(wù)準(zhǔn)備運(yùn)行*/ #endif INT16U OSTCBDly; /* 任務(wù)等待的時(shí)限*/ INT8U OSTCBSt
6、at; /* 任務(wù)的當(dāng)前狀態(tài)標(biāo)志 */ INT8U OSTCBPrio; /* 任務(wù)優(yōu)先級(jí) (0 = highest, 63 = lowest) */ /*以下四行語(yǔ)句用于快速訪(fǎng)問(wèn)就緒表的數(shù)據(jù)*/ INT8U OSTCBX; /* Bit position in group corresponding to task priority (0.7) */ INT8U OSTCBY; /* Index into ready table corresponding to task priority */ INT8U OSTCBBitX; /* Bit mask to access bit posit
7、ion in ready table */ INT8U OSTCBBitY; /* Bit mask to access bit position in ready group */ #if OS_TASK_DEL_EN 0 BOOLEAN OSTCBDelReq; /* Indicates whether a task needs to delete itself */ #endif /* 以下代碼是我自己加的:*/#ifdef OS_TIME_SCHEDULE struct os_tcb *OSTSnext; struct os_tcb *OSTSprev; INT8U OSTSLen;
8、/*記錄了該進(jìn)程占用多少個(gè)時(shí)間片*/ INT8U OSTSCurLen; /*記錄的是該進(jìn)程現(xiàn)在還剩下多少個(gè)時(shí)間片時(shí)間可以用*/#endif /*/ OS_TCB; 三.進(jìn)程創(chuàng)建 進(jìn)程創(chuàng)建的主要目的是跳過(guò)原代碼中的優(yōu)先級(jí)占用檢查,并在這里加入 FIFO 進(jìn)程創(chuàng)建。 文件在OS_TASK.C中: INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio,INT16U id, INT8U TSlen) #if OS_CRITICAL_METHOD = 3 /* 為CPU狀態(tài)寄存器分配存儲(chǔ)空間*
9、/ OS_CPU_SR cpu_sr; /CPU狀態(tài)字是十六位cpu_sr為OS_CPU_SR型變量#endif OS_STK *psp; /創(chuàng)建一個(gè)指向數(shù)據(jù)類(lèi)型為OS_STK的指針和一個(gè)8位的整型數(shù) INT8U err; #if OS_ARG_CHK_EN 0 if (prio OS_LOWEST_PRIO) /*保證優(yōu)先級(jí)在允許范圍內(nèi) */ return (OS_PRIO_INVALID); #endif OS_ENTER_CRITICAL(); /* OS_ENTER_CRITICAL()和OS_EXIT_CRITICAL()為定義的宏,用來(lái)關(guān)閉、打開(kāi)CPU 的中斷。*/ if (OST
10、CBPrioTblprio = (OS_TCB *)0) /*保證優(yōu)先級(jí)沒(méi)有被其它任務(wù)占用 */ /* * if you want run the FIFO mask this code OSTCBPrioTblprio = (OS_TCB *)1; /* Reserve the priority to preventothers from doing . */ /* . the same thing until task is created. */那就是說(shuō)有一個(gè)任務(wù)存在了,不再是 Nul /*/ OS_EXIT_CRITICAL(); psp = (OS_STK *)OSTaskStkIn
11、it(task, pdata, ptos, 0); /* 初始化任務(wù)堆棧,即建立任務(wù)堆棧*/ err = OS_TCBInit(prio, psp, (OS_STK *)0, id, 0, (void *)0, 0, TSlen); /*初始化任務(wù)控制塊,從空閑的OS_TCB緩沖池中獲得并初始化一個(gè)任務(wù)控制塊*/if (err = OS_NO_ERR) /如果初始化沒(méi)有錯(cuò) OS_ENTER_CRITICAL();/進(jìn)入臨界狀態(tài) OSTaskCtr+; /*任務(wù)數(shù)量加一*/ OS_EXIT_CRITICAL(); if (OSRunning = TRUE) /* 如果多任務(wù)開(kāi)始,尋找最高優(yōu)先級(jí)任
12、務(wù) */ OS_Sched(); else /如果初始化任務(wù)控制塊有錯(cuò) OS_ENTER_CRITICAL(); OSTCBPrioTblprio = (OS_TCB *)0;/* Make this priority available to others 把這一優(yōu)先級(jí)給其它任務(wù)*/ OS_EXIT_CRITICAL(); return (err); /返回錯(cuò)誤信息/* */ else /這是FIFO的任務(wù)創(chuàng)建代碼 OS_EXIT_CRITICAL(); psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0); /* Initialize th
13、etasks stack初始化任務(wù)堆棧,即建立任務(wù)堆棧*/ err = OS_TCBInit(prio, psp, (OS_STK *)0, id, 0, (void *)0, 0, TSlen); if (err = OS_NO_ERR) OS_ENTER_CRITICAL(); OSTaskCtr+; /*任務(wù)數(shù)量加一*/ OS_EXIT_CRITICAL(); if (OSRunning = TRUE) /* Find highest priority task if multitaskinghas started */ OS_Sched(); return(err); /*/ OS_E
14、XIT_CRITICAL(); return (OS_PRIO_EXIST); 其中加入的傳遞參數(shù)有兩個(gè),一個(gè)是 id,一個(gè)是 TSLen 因?yàn)闀?huì)出現(xiàn)同優(yōu)先級(jí)的任務(wù),那么采用優(yōu)先級(jí)做為任務(wù) ID 的方式是不可取的了,我們必須加入任務(wù) id 段 TSLen 段,是該進(jìn)程的時(shí)間片為多長(zhǎng)。 四.進(jìn)程初始化 進(jìn)程初始化基本保留以前的東西不動(dòng),要的就僅僅是把 TSLen 加入 TCB,把上面說(shuō)到的那個(gè)鏈表鏈接起來(lái)。 代碼在文件OS_CORE.C中初始化任務(wù)控制塊1. 參數(shù):prio:任務(wù)創(chuàng)建時(shí)的優(yōu)先級(jí)2. ptos:假定CPU寄存器放置于堆棧中指向堆棧棧頂?shù)闹羔槨m敭?dāng)OS_STK_GROWTH為1時(shí)是
15、寄存器的高位、當(dāng)OS_STK_GROWTH為0時(shí)是寄存器的低位,堆棧增長(zhǎng)是CPU的特權(quán)。3. pbos:棧底指針。由OSTaskCreate()調(diào)用時(shí)傳入空指針。4. id:任務(wù)的ID5. stk_size:堆棧大小。當(dāng)堆棧單位是int8us時(shí),堆棧大小包含堆棧數(shù)量個(gè)字節(jié),當(dāng)堆棧單位是int32us時(shí),堆棧大小包含“4*stk_size”個(gè)字節(jié)。堆棧單位由“#defineconstantOS_STK”建立,它是CPU特有。如果被OSTaskCreate()調(diào)用stk_size為0。6. pext:用戶(hù)提供存儲(chǔ)器空間的指針,用于任務(wù)控制塊。允許存儲(chǔ)浮點(diǎn)寄存器常量,MMU寄存器或者其它在內(nèi)容轉(zhuǎn)換時(shí)
16、有用的東西。甚至在TCB擴(kuò)展中為每個(gè)任務(wù)指定一個(gè)名字存到這個(gè)名字里面。OSTaskCreate()調(diào)用的時(shí)候?yàn)榭罩羔槨? opt:傳到OSTaskCreateExt()時(shí)可以選擇,被OSTaskCreate()調(diào)用的時(shí)候?yàn)?。 INT8U OS_TCBInit (INT8U prio, OS_STK *ptos, OS_STK *pbos, INT16U id, INT32U stk_size, void *pext, INT16U opt, INT8U TSlen) #if OS_CRITICAL_METHOD = 3 /*為CPU狀態(tài)寄存器分配存儲(chǔ)空間 */ OS_CPU_SR cpu_s
17、r; #endif OS_TCB *ptcb; OS_ENTER_CRITICAL(); ptcb = OSTCBFreeList; /*從空TCB列表中得到一塊空TCB */ if (ptcb != (OS_TCB *)0) /分配空TCB成功 OSTCBFreeList = ptcb-OSTCBNext; /*更新空閑TCB鏈表頭指針 */ OS_EXIT_CRITICAL(); ptcb-OSTCBStkPtr = ptos; /*保存棧頂指針到TCB */ ptcb-OSTCBPrio = (INT8U)prio; /*保存任務(wù)優(yōu)先級(jí)到TCB */ ptcb-OSTCBStat = O
18、S_STAT_RDY; /*任務(wù)狀態(tài)設(shè)為就緒*/ ptcb-OSTCBDly = 0; /*任務(wù)不延時(shí)*/ #if OS_TASK_CREATE_EXT_EN 0 ptcb-OSTCBExtPtr = pext; /*存儲(chǔ)TCB擴(kuò)展指針*/ ptcb-OSTCBStkSize = stk_size; /*存儲(chǔ)堆棧大小 */ ptcb-OSTCBStkBottom = pbos; /*存儲(chǔ)棧底指針*/ ptcb-OSTCBOpt = opt; /*存儲(chǔ)任務(wù)選項(xiàng) */ #else /以下四條語(yǔ)句用于防止編譯器警告,不要?jiǎng)h除 pext = pext; /* Prevent compiler warn
19、ing if not used */ stk_size = stk_size; pbos = pbos; opt = opt; #endif ptcb-OSTCBId = id; /* 存儲(chǔ)任務(wù)ID */ #if OS_TASK_DEL_EN 0 /允許包含任務(wù)刪除代碼 ptcb-OSTCBDelReq = OS_NO_ERR; /是否允許自動(dòng)刪除#endif ptcb-OSTCBY = prio 3; /*提前計(jì)算X,Y,位X,位Y*/ ptcb-OSTCBBitY = OSMapTblptcb-OSTCBY; ptcb-OSTCBX = prio & 0x07; /* 存儲(chǔ)就緒優(yōu)先級(jí)組中的
20、 8 個(gè)優(yōu)先級(jí)情況 */ ptcb-OSTCBBitX = OSMapTblptcb-OSTCBX; /*為什么要這樣算?不知道*/ #if OS_EVENT_EN 0 ptcb-OSTCBEventPtr = (OS_EVENT *)0; /* 任務(wù)不等待任何事件發(fā)生*/ #endif #if (OS_VERSION = 251) & (OS_FLAG_EN 0) & (OS_MAX_FLAGS 0) & (OS_TASK_DEL_EN 0) /*OS版本大于等于251&能使事件標(biāo)志代碼產(chǎn)生&最大標(biāo)志數(shù)大于零&允許包含任務(wù)刪除函數(shù)*/ ptcb-OSTCBFlagNode = (OS_FLA
21、G_NODE *)0; /* 任務(wù)不等待事件標(biāo)志*/ #endif #if (OS_MBOX_EN 0) | (OS_Q_EN 0) & (OS_MAX_QS 0) /允許郵箱代碼產(chǎn)生|允許隊(duì)列代碼產(chǎn)生&最大隊(duì)列控制塊大于零 ptcb-OSTCBMsg = (void *)0; /*沒(méi)有接收到任務(wù)消息*/ #endif ptcb-OSTSLen=TSlen; ptcb-OSTSCurLen=TSlen; #if OS_VERSION = 204 /ucos版本大于等于204 OSTCBInitHook(ptcb); #endif OSTaskCreateHook(ptcb); /* Call
22、user defined hook */ OS_ENTER_CRITICAL(); if(OSTCBPrioTblprio = 0) OSTCBPrioTblprio = ptcb; /*任務(wù)控制塊存入到已創(chuàng)建任務(wù)控制塊列表當(dāng)中*/ ptcb-OSTSnext = ptcb; ptcb-OSTSprev = ptcb; else ptcb-OSTSnext = OSTCBPrioTblprio-OSTSnext; OSTCBPrioTblprio-OSTSnext = ptcb; ptcb-OSTSprev = OSTCBPrioTblprio; (ptcb-OSTSnext )-OSTSpr
23、ev=ptcb; ptcb-OSTCBNext = OSTCBList; /* Link into TCB chain */ ptcb-OSTCBPrev = (OS_TCB *)0; if (OSTCBList != (OS_TCB *)0) OSTCBList-OSTCBPrev = ptcb; OSTCBList = ptcb; OSRdyGrp |= ptcb-OSTCBBitY; /* Make task ready to run */ OSRdyTblptcb-OSTCBY |= ptcb-OSTCBBitX; OS_EXIT_CRITICAL(); return (OS_NO_E
24、RR); OS_EXIT_CRITICAL(); return (OS_NO_MORE_TCB); if(OSTCBPrioTblprio = 0) OSTCBPrioTblprio = ptcb; ptcb-OSTSnext = ptcb; ptcb-OSTSprev = ptcb; else ptcb-OSTSnext = OSTCBPrioTblprio-OSTSnext; OSTCBPrioTblprio-OSTSnext = ptcb; ptcb-OSTSprev = OSTCBPrioTblprio; (ptcb-OSTSnext )-OSTSprev=ptcb; 這一段解釋一下
25、鏈表必須進(jìn)行鏈接,在優(yōu)先級(jí)沒(méi)有被占用的時(shí)候,這個(gè)鏈表的前后都鏈向自己,這樣在調(diào)度的時(shí)候,F(xiàn)IFO 調(diào)度就算指向下個(gè)任務(wù),也指向的是自己,不影響優(yōu)先級(jí)調(diào)度。 當(dāng)在這個(gè)優(yōu)先級(jí)已經(jīng)有進(jìn)程的時(shí)候,那么我們需要的就是把這個(gè)進(jìn)程加入到這個(gè)優(yōu)先級(jí)的鏈表中,鏈表操作相信大家都能看懂,不多做解釋。 五.進(jìn)程調(diào)度 進(jìn)程調(diào)度基本還是依靠 UCOS 自己的調(diào)度算法,修改的,就僅僅是在調(diào)度之間,把運(yùn)行態(tài)優(yōu)先級(jí)的任務(wù)進(jìn)行運(yùn)算,時(shí)間片使用完,就指向下一個(gè)進(jìn)程。 OS_CORE.C void OSTimeTick (void) #if OS_CRITICAL_METHOD = 3 /* Allocate storage fo
26、r CPU status register */ OS_CPU_SR cpu_sr; #endif OS_TCB *ptcb; OSTimeTickHook(); /* Call user definable hook */ #if OS_TIME_GET_SET_EN 0 OS_ENTER_CRITICAL(); /* Update the 32-bit tick counter */ OSTime+; /*系統(tǒng)節(jié)拍現(xiàn)階段值,計(jì)算自系統(tǒng)上電以來(lái)的時(shí)鐘節(jié)拍數(shù)*/ OS_EXIT_CRITICAL(); #endif if(OSTCBCur-OSTSCurLen)0)/如果時(shí)間片沒(méi)有用完 if(
27、-OSTCBCur-OSTSCurLen=0)/時(shí)間片在這次調(diào)度中用完了 if(OSTCBCur-OSTSnext != OSTCBCur)/*如果優(yōu)先級(jí)里面至少有兩個(gè)進(jìn)程(看上一篇文章來(lái)理解這個(gè)地方)*/ OSTCBCur-OSTSCurLen = OSTCBCur-OSTSLen;/*把現(xiàn)在時(shí)間片用完的進(jìn)程的時(shí)間補(bǔ)回來(lái),以便下次調(diào)度*/ OSTCBPrioTblOSTCBCur-OSTCBPrio = OSTCBCur-OSTSnext;/*把該優(yōu)先級(jí)的任務(wù)替換成下一個(gè)任務(wù)*/ OSPrioCur=0;/把當(dāng)前的運(yùn)行優(yōu)先級(jí)改成 0,不然調(diào)度認(rèn)為該優(yōu)先級(jí)的任務(wù)沒(méi)有結(jié)束,不執(zhí)行任務(wù)調(diào)度,結(jié)果回到的地方,還是上一個(gè)時(shí)間片的任務(wù),就死翹翹了! ptcb = OSTCBList; /* Point at first TCB in TCB list */ while (ptcb-OSTCBPrio != OS_IDLE_PRIO) /*空閑任務(wù)處于控制塊雙向鏈表的最后一個(gè)
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 七年級(jí)信息技術(shù)上冊(cè) 第8課 計(jì)算機(jī)數(shù)據(jù)安全教案 川教版
- 廣東省揭陽(yáng)市第一中學(xué)高中信息技術(shù)《網(wǎng)絡(luò)技術(shù)應(yīng)用》第二章 第三課 如何將計(jì)算機(jī)接入因特網(wǎng)教案
- 福建省漳州市云霄縣七年級(jí)生物上冊(cè) 第三單元 第三章 綠色植物與生物圈的水循環(huán)教案 (新版)新人教版
- 七年級(jí)語(yǔ)文上冊(cè) 6從百草園到三味書(shū)屋教案 長(zhǎng)春版
- 湖南省益陽(yáng)市八年級(jí)地理下冊(cè) 第十章 中國(guó)在世界中知識(shí)梳理型教案 (新版)湘教版
- 三年級(jí)思品與社會(huì)上冊(cè) 我們的班集體教案 北師大版
- 河北省秦皇島市撫寧縣駐操營(yíng)學(xué)區(qū)初級(jí)中學(xué)初中信息技術(shù)《數(shù)據(jù)的輸入》教學(xué)設(shè)計(jì)
- 八年級(jí)歷史下冊(cè) 第4課 走向國(guó)際舞臺(tái)教學(xué)設(shè)計(jì) 北師大版
- 七年級(jí)道德與法治上冊(cè) 第三單元 師長(zhǎng)情誼 第六課 師生之間 第2框師生交往教案 新人教版
- 終止電梯保養(yǎng)合同模板
- 22.2-二次函數(shù)與一元二次方程
- (完整版)管理評(píng)審記錄
- 【高一物理課堂教學(xué)反思范文】 課堂教學(xué)反思20篇簡(jiǎn)短
- 華為性格測(cè)試分類(lèi)整理
- 高碳鉻鐵冶煉工藝技術(shù)操作規(guī)程
- 精神獎(jiǎng)勵(lì)比物質(zhì)獎(jiǎng)勵(lì)更重要一辯陳詞
- 童話(huà)(光良)原版五線(xiàn)譜鋼琴譜正譜樂(lè)譜.docx
- 淀粉的種類(lèi)和使用
- 定植與感染如何區(qū)分
- 學(xué)前教育專(zhuān)業(yè)《聲樂(lè)》核心課程標(biāo)準(zhǔn)
- 危險(xiǎn)化學(xué)品專(zhuān)項(xiàng)預(yù)案演練記錄
評(píng)論
0/150
提交評(píng)論