ucos 統計任務 OS TaskStat

2022-02-06 16:06:51 字數 3602 閱讀 6848

先把ucosii中的原文寫在這,然後再說一下我的具體理解。

μc/os-ⅱ有乙個提供執行時間統計的任務。這個任務叫做os_taskstat(),如果使用者將系統定義常數os_task_stat_en(見檔案os_cfg.h)設為1,這個任務就會建立。一旦得到了允許,os_taskstat()每秒鐘執行一次(見檔案os_core.c),計算當前的cpu利用率。換句話說,os_taskstat()告訴使用者應用程式使用了多少cpu時間,用百分比表示,這個值放在乙個有符號8位整數oscpusage中,精讀度是1個百分點。

如果使用者應用程式打算使用統計任務,使用者必須在初始化時建立乙個唯一的任務,在這個任務中呼叫osstatinit()。換句話說,在呼叫系統啟動函式osstart()之前,使用者初始**必須先建立乙個任務,在這個任務中呼叫系統統計初始化函式osstatinit(),然後再建立應用程式中的其它任務。程式清單l3.12是統計任務的示意性**。

程式清單 l3.12 初始化統計任務.

void main (void)

void taskstart (void *pdata)

}因為使用者的應用程式必須先建立乙個起始任務[taskstart()],當主程式main()呼叫系統啟動函式osinit()的時候,μc/os-ⅱ只有3個要管理的任務:taskstart()、ostaskidle()和os_taskstat()。請注意,任務taskstart()的名稱是無所謂的,叫什麼名字都可以。因為μc/os-ⅱ已經將空閒任務的優先順序設為最低,即os_lowest_pr10,統計任務的優先順序設為次低,os_lowest_pr10減1。啟動任務taskstart()總是優先順序最高的任務。

圖f3.4解釋初始化統計任務時的流程。使用者必須首先呼叫的是μc/os-ⅱ中的系統初始化函式osinit(),該函式初始化μc/os-ⅱ[圖f3.4(2)]。有的處理器(例如motorola的mc68hc11),不需要「設定」中斷向量,中斷向量已經在rom中有了。使用者必須呼叫ostaskcreat()或者ostaskcreatext()以建立taskstart()[圖f3.4(3)]。進入多工的條件準備好了以後,呼叫系統啟動函式osstart()。這個函式將使taskstart()開始執行,因為taskstart()是優先順序最高的任務[圖f3.4(4)]]。

taskstart()負責初始化和啟動時鐘節拍[圖f3.4(5)]。在這裡啟動時鐘節拍是必要的,因為使用者不會希望在多工還沒有開始時就接收到時鐘節拍中斷。接下去taskstart()呼叫統計初始化函式osstatinit()[圖f3.4(6)]。統計初始化函式osstatinit()決定在沒有其它應用任務執行時,空閒計數器(osidlectr)的計數有多快。奔騰ii微處理器以333mhz執行時,加1操作可以使該計數器的值達到每秒15,000,000次。osidlectr的值離32位計數器的溢位極限值4,294,967,296還差得遠。微處理器越來越快,使用者要注意這裡可能會是將來的乙個潛在問題。

系統統計初始化任務函式osstatinit()呼叫延遲函式ostimedly()將自身延時2個時鐘節拍以停止自身的執行[圖f3.4(7)]。這是為了使osstatinit()與時鐘節拍同步。μc/os-ⅱ然後選下乙個優先順序最高的進入就緒態的任務執行,這恰好是統計任務ostaskstat()。讀者會在後面讀到ostaskstat()的**,但粗看一下,ostaskstat()所要做的第一件事就是檢視統計任務就緒標誌是否為「假」,如果是的話,也要延時兩個時鐘節拍[圖f3.4(8)]。一定會是這樣,因為標誌osstatrdy已被osinit()函式初始化為「假」,所以實際上dstaskstat也將自己推入休眠態(sleep)兩個時鐘節拍[圖f3.4(9)]。於是任務切換到空閒任務,ostaskidle()開始執行,這是唯一乙個就緒態任務了。cpu處在空閒任務ostaskidle中,直到taskstart()的延遲兩個時鐘節拍完成[圖3.4(10)]。兩個時鐘節拍之後,taskstart()恢復執行[圖f3.4(11)]。 在執行osstartinit()時,空閒計數器osidlectr被清零[圖f3.4(12)]。然後,osstatinit()將自身延時整整一秒[圖f3.4(13)]。因為沒有其它進入就緒態的任務,ostaskidle()又獲得了cpu的控制權[圖f3.4(14)]。一秒鐘以後,taskstart()繼續執行,還是在osstatinit()中,空閒計數器將1秒鐘內計數的值存入空閒計數器最大值osidlectrmax中[圖f3.4(15)]。

osstarinit()將統計任務就緒標誌osstatrdy設為「真」[圖f3.4(16)],以此來允許兩個時鐘節拍以後ostaskstat()開始計算cpu的利用率。

統計任務的初始化函式osstatinit()的**如程式清單 l3.13所示。

程式清單 l3.13 統計任務的初始化.

void osstatinit (void)

統計任務osstat()的**程式清單l3.14所示。在前面一段中,已經討論了為什麼要等待統計任務就緒標誌osstatrdy[l3.14(1)]。這個任務每秒執行一次,以確定所有應用程式中的任務消耗了多少cpu時間。當使用者的應用程式**加入以後,執行空閒任務的cpu時間就少了,osidlectr就不會像原來什麼任務都不執行時有那麼多計數。要知道,osidlectr的最大計數值是osstatinit()在初始化時儲存在計數器最大值osidlectrmax中的。cpu利用率(表示式[3.1])是儲存在變數oscpusage[l3.14(2)]中的:

[3.1]表示式 need to typeset the equation.

一旦上述計算完成,ostaskstat()呼叫任務統計外界接入函式ostaskstathook() [l3.14(3)],這是乙個使用者可定義的函式,這個函式能使統計任務得到擴充套件。這樣,使用者可以計算並顯示所有任務總的執行時間,每個任務執行時間的百分比以及其它資訊(參見1.09節例3)。

程式清單 l3.14 統計任務

void ostaskstat (void *pdata)

for (;;) else if (usage < 0) else

} else

ostaskstathook(); (3)

ostimedly(os_ticks_per_sec);}}

還是先仔細看看原始碼,這樣有利於你搞明白統計任務的實現原理和應用方法。

下面我說一下我個人的理解:

統計任務的實現原理大致上是這樣的,一開始統計任務要初始化,主要是保證μc/os-ⅱ的空閒任務準時執行1s的時間。我們看看這個任務都幹些什麼。

void ostaskidle (void *pdata)

}這個任務其實就是給乙個osidlectr這個變數加一。這樣在保證空閒任務執行1s的時間內,就把1s內空閒任務中osidlectr變數達到此次開機的最大值。而且在初始化統計任務中把這個變數的值賦給了osidlectrmax 這個變數。如果不重啟的話,這個值是不變的。用這個值來算以後有了其他任務時cpu的利用率。具體怎麼實現的計算和怎麼實現的一開始讓空閒任務執行1s的。可以看上面的原始碼。其中,我用紅色字型標出的,為了保證空閒任務執行1s,初始化統計任務時我們讓其延時了2s。看原始碼就會知道。

至於,啟動多工之後,統計任務如何計算cpu利用率的,書上說的統計任務每秒執行一次(ucos是實時作業系統,可以做到),大家可以想一想,統計任務執行到最後時是ostimedly(os_ticks_per_sec);這樣乙個函式。表示延遲一秒。而只有統計任務延時時空閒任務才有可能執行,所以每當統計任務執行時osidlectr的值都是在可能的1s內記的數。因為在統計任務在賦完值之後清零了。所以,用統計任務可以統計cpu利用率。

ucos任務排程

1 ostimedly產生延時,假設當前任務a呼叫ostimedly函式,則ostimedly函式就將任務a從任務就緒表中去掉,並將延時時間賦值給任務a的任務控制塊中的ostcbdly,然後呼叫os sched。2 os sched函式,它利用任務就緒表,將就緒任務中的優先順序最高的任務查出,賦值給...

ucos任務排程

實現任務切換,需要呼叫函式ossched void ossched void int8u y os enter critical if oslocknesting osintnesting 0 1 y osunmaptbl osrdygrp ospriohighrdy int8u y 3 osunm...

ucos任務掛起

建立好了任務之後,就已經初步跨進了ucosii的程式設計了,隨著進一步的程式設計,發現學會建立了任務還是不夠的,建立任務1用於串列埠1傳送資料,任務2用於串列埠1接收資料,程式本身的意圖是傳送完資料後,接著就串列埠1接收反饋回來的資訊,但是不能正常通訊,原因就是當任務1在傳送資料過程 cpu時不是會...