?? ——uc-os-ii任務(wù)棧處理的一種改進(jìn)方法.htm
字號:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<!-- saved from url=(0061)http://www.21ic.com/new_info/news/files/news/200381803435.asp -->
<HTML><HEAD><TITLE>——uC/OS-II任務(wù)棧處理的一種改進(jìn)方法</TITLE>
<META http-equiv=Content-Type content="text/html; charset=gb2312">
<STYLE type=text/css>TD {
FONT-SIZE: 12px
}
INPUT {
FONT-SIZE: 12px; font-fammily: verdana,宋體
}
A:link {
FONT-SIZE: 12px; COLOR: #0000ff; LINE-HEIGHT: 16px; TEXT-DECORATION: underline
}
A:visited {
FONT-SIZE: 12px; COLOR: #660066; LINE-HEIGHT: 16px; TEXT-DECORATION: underline
}
A:hover {
FONT-SIZE: 12px; COLOR: #ff0000; TEXT-DECORATION: underline
}
.unnamed1 {
FONT-SIZE: 12px; FONT-FAMILY: "Arial", "Helvetica", "sans-serif"
}
.white {
FONT-SIZE: 12px; COLOR: #ffffff; LINE-HEIGHT: 16px
}
.b:link {
FONT-SIZE: 12px; COLOR: #3366cc; LINE-HEIGHT: 18px; TEXT-DECORATION: underline
}
.b:visited {
FONT-SIZE: 12px; COLOR: #813f1b; LINE-HEIGHT: 18px; TEXT-DECORATION: none
}
.b:hover {
FONT-SIZE: 12px; COLOR: #ffa037; LINE-HEIGHT: 18px; TEXT-DECORATION: underline
}
.148xg {
FONT-SIZE: 14px; COLOR: #0000ff; LINE-HEIGHT: 14pt; FONT-FAMILY: "宋體"; TEXT-DECORATION: underline
}
.128dt {
FONT-SIZE: 14px; COLOR: #9999cc; LINE-HEIGHT: 14pt; FONT-FAMILY: "宋體"; TEXT-DECORATION: none
}
.heigh150 {
LINE-HEIGHT: 150%
}
</STYLE>
<META content="MSHTML 6.00.2600.0" name=GENERATOR></HEAD>
<BODY text=#000000 bgColor=#ffffff leftMargin=0 topMargin=5>
<TABLE cellSpacing=0 cellPadding=0 width=768 align=center border=0>
<TBODY>
<TR>
<TD align=middle width=168 height=80><IMG
src="——uC-OS-II任務(wù)棧處理的一種改進(jìn)方法.files/21ic.gif"></TD>
<TD width=472>
<SCRIPT language=javascript
src="——uC-OS-II任務(wù)棧處理的一種改進(jìn)方法.files/ads.htm"></SCRIPT>
</TD>
<TD height=80>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD class=b12 align=middle height=30><FONT
face="Arial, Helvetica, sans-serif" color=#000000>
<SCRIPT language=JavaScript
src="——uC-OS-II任務(wù)棧處理的一種改進(jìn)方法.files/date.js"></SCRIPT>
</FONT></TD></TR></TBODY></TABLE></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=1 width=768 align=center border=0>
<TBODY>
<TR>
<TD>
<TABLE cellSpacing=0 cellPadding=3 width=766 align=left border=0>
<TBODY>
<TR bgColor=#d8d6ba>
<TD width=3 height=20></TD>
<DIV id=Position></DIV>
<TD width=378>
<FORM name=email
action=http://www.21icsearch.com/buzi/mail2/chkemail.asp method=post
target=_blank><B>電子工程周刊:</B> <INPUT class=main
style="BORDER-RIGHT: #0097cf 1px solid; BORDER-TOP: #0097cf 1px solid; BORDER-LEFT: #0097cf 1px solid; BORDER-BOTTOM: #0097cf 1px solid; BACKGROUND-COLOR: #ffffff"
maxLength=255 size=30 value=輸入您的Email name=email> <INPUT class=jbutton type=submit value=訂閱> </TD></FORM>
<DIV></DIV>
<DIV id=Time></DIV>
<DIV id=Image></DIV>
<DIV id=Title></DIV>
<TD width=418>
<MARQUEE onmouseover=this.scrollDelay=99000
onmouseout=this.scrollDelay=80 scrollAmount=2 scrollDelay=80
width="80%"><FONT color=#cc0000><IMG height=12
src="——uC-OS-II任務(wù)棧處理的一種改進(jìn)方法.files/xilan_arrow.gif"
width=16>每周自動接收行業(yè)新聞,技術(shù)資料,設(shè)計(jì)文章</FONT></MARQUEE></TD>
<DIV></DIV>
<TD width=9></TD></TR></TBODY></TABLE>
<DIV></DIV>
<DIV id=Time></DIV>
<DIV id=Image></DIV>
<DIV id=Title><TD< td></DIV></TD></TR></TBODY></TABLE></TD></TR></TABLE><BR>
<TABLE cellSpacing=0 cellPadding=0 width=768 align=center border=0>
<TBODY>
<TR>
<TD vAlign=top width=617 height=2>
<TABLE cellSpacing=0 cellPadding=0 width=583 align=center border=0>
<TBODY>
<TR>
<TD align=middle height=31><FONT size=4><B>uC/OS-II任務(wù)棧處理的一種改進(jìn)方法
</B></FONT></TD></TR>
<TR>
<TD align=middle height=15>文章作者:彭良清<BR>文章類型:設(shè)計(jì)應(yīng)用
文章加入時(shí)間:2003年8月18日0:34</TD></TR>
<TR>
<TD align=right><FONT color=#cc0000>文章出處:單片機(jī)及嵌入式系統(tǒng)應(yīng)用</FONT> </TD></TR>
<TR>
<TD height=15>
<HR width="100%" noShade SIZE=1>
</TD></TR>
<TR>
<TD height=15>
<TABLE cellSpacing=0 cellPadding=0 align=center border=0>
<TBODY>
<TR>
<TD></TD></TR></TBODY></TABLE><BR></TD></TR></TBODY></TABLE>
<TABLE cellSpacing=0 cellPadding=0 width=530 align=center border=0>
<TBODY>
<TR>
<TD class=heigh150 height=15>
<DIV id=Content>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
<B>摘要:</B></SPAN>在μC/OS-II內(nèi)核中,各個(gè)不同的任務(wù)使用獨(dú)立的堆棧空間,堆棧的大小按每個(gè)任務(wù)所需要的最大堆棧深度來定義,這種方法可能會造成堆??臻g浪費(fèi)。本文敘述如何在RTOS中多個(gè)任務(wù)共用連續(xù)存儲空間作為任務(wù)棧的方法,并詳細(xì)比較二者的優(yōu)缺點(diǎn)和適用性。</P>
<P class=MsoNormal><SPAN
style="FONT-FAMILY: 宋體; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">
<B>關(guān)鍵詞:</B></SPAN>μC/OS-II 任務(wù)堆棧 RTOS 共用空間堆棧</P>
<P
style="TEXT-INDENT: 30px">關(guān)于μC/OS-II這個(gè)實(shí)時(shí)內(nèi)核及其應(yīng)用已經(jīng)有很多文章介紹了,對于學(xué)習(xí)RTOS的人來說,這個(gè)系統(tǒng)是很好的學(xué)習(xí)起點(diǎn)。雖然文獻(xiàn)[1]的源代碼沒有行號和函數(shù)名交叉索引表等,給源代碼閱讀造成一些困難(可使用BC31的grep查找功能,提高閱讀效率),好在代碼不是很長,前面又有詳細(xì)的中文說明,對于有一定X86匯編和C語言基礎(chǔ)的人來說,仍然可以在不長的時(shí)間內(nèi)掌握。</P>
<P
style="TEXT-INDENT: 30px">μC/OS-II內(nèi)核是一個(gè)搶先式內(nèi)核,可以進(jìn)行任務(wù)間切換,也可以讓一個(gè)任務(wù)在得不到某個(gè)資源時(shí)休眠一定時(shí)間后再繼續(xù)運(yùn)行;提供了用于共享資源管理的信號燈,用于進(jìn)程通信的消息隊(duì)列和郵箱,甚至提供了存儲器管理機(jī)制,一個(gè)比較全面的系統(tǒng)。</P>
<P
style="TEXT-INDENT: 30px">μC/OS-II內(nèi)核有些地方仍然值得改進(jìn),比如該系統(tǒng)不支持時(shí)間片調(diào)度。如果有一個(gè)任務(wù)中一段死循環(huán)代碼(或者條件循環(huán)代碼),代碼就會永遠(yuǎn)(或長時(shí)間)在此處執(zhí)行,調(diào)度程序無法控制,其它任務(wù)也就是不到及時(shí)執(zhí)行。這種搶先式實(shí)際上和非搶先式系統(tǒng)存在著同樣問題。當(dāng)然,如果這種代碼不一個(gè)BUG,問題是可以解決的,在不提供時(shí)間片調(diào)度的搶先式系統(tǒng)中,一般采取信號燈,或者任務(wù)主動休眠的方法(對于μC/OS-II,很容易改造成支持時(shí)間片調(diào)度,只要在定時(shí)中斷服務(wù)程序調(diào)用OSIntCtxSw()函數(shù)即可);非搶先式系統(tǒng)一般采取有限狀態(tài)機(jī)方法,不使用這種耗時(shí)很長的循環(huán)代碼。不過,無論如何,對RTOS的使用者來說,這畢竟會使得任務(wù)函數(shù)的編碼不能隨心所欲。</P>
<P
style="TEXT-INDENT: 30px">ΜC/OS-II內(nèi)核的另外一個(gè)值得改進(jìn)的地方就是其任務(wù)棧管理方法。在μC/OS-II內(nèi)核中,各個(gè)不同的任務(wù)使用獨(dú)立的堆棧空間,堆棧的大小按每個(gè)任務(wù)所需要的最大堆棧深度來定義,這種方法可能會造成堆??臻g的浪費(fèi)。下面討論如何在RTOS中多個(gè)任務(wù)共用一段連續(xù)存儲空間作為傻堆棧。<B><BR><IMG
height=246 hspace=10 src="——uC-OS-II任務(wù)棧處理的一種改進(jìn)方法.files/5a.gif"
width=549 vspace=10 border=0><BR>1 任務(wù)切換要保存的數(shù)據(jù)</B></P>
<P
style="TEXT-INDENT: 30px">簡單地說,一個(gè)任務(wù)可看作一個(gè)運(yùn)行中的C函數(shù)。對于搶先式RTOS來說,在任務(wù)切換時(shí),應(yīng)保存當(dāng)前任務(wù)的各種現(xiàn)場數(shù)據(jù)。現(xiàn)場數(shù)據(jù)包括局部變量、各個(gè)CPU寄存器、堆棧指針和程序被中止的任務(wù)指針。CPU寄存器是任何任務(wù)代碼均會用到的;而局部變量,一般的編譯器是將其它安排在堆??臻g中,堆棧指針也是各任務(wù)公用的,所以也需要保存。</P>
<P
style="TEXT-INDENT: 30px">對于全局變量,由于一般是在內(nèi)存中的固定位置,各任務(wù)所占用的空間完全獨(dú)立,所以不需要保存。</P>
<P
style="TEXT-INDENT: 30px">在X86環(huán)境中,要保存的CPU寄存器共14個(gè)16位寄存器;通用寄存器8個(gè)(AX、BX、CX、DX、SP、BP、SI、BI)、段寄存器4個(gè)(CS、DS、ES、SS)以及指令指針I(yè)P和標(biāo)志寄存器FR各1個(gè)。</P>
<P style="TEXT-INDENT: 0px"><B>2 C編譯器中變量在堆棧中的位置</B></P>
<P
style="TEXT-INDENT: 30px">對于一個(gè)存在函數(shù)調(diào)用嵌套的C程序來說,大部分編譯器將傳遞的參數(shù)和函數(shù)本身的局部變量放在了堆棧中,編譯器會自動生成壓棧(push)和彈棧(pop)代碼,以保存上級函數(shù)的運(yùn)行寄存器。</P>
<P
style="TEXT-INDENT: 30px">假設(shè)函數(shù)main()調(diào)用funl(),而funl()調(diào)用fun2(),則在執(zhí)行fun2()中的代碼時(shí),堆棧映像如圖1所示(X86
CPU的情況)。</P>
<P
style="TEXT-INDENT: 30px">對于RTOS軟件,堆棧中的各種數(shù)據(jù)就是一個(gè)任務(wù)的作現(xiàn)場。一般CPU的堆棧指針SP只有一個(gè),在進(jìn)行任務(wù)切換時(shí),必須將掛起任務(wù)所使用的堆棧內(nèi)容保存起來,以便使該任務(wù)在下次喚醒時(shí)能從原地繼續(xù)運(yùn)行。</P>
<P style="TEXT-INDENT: 0px"><B>3 μC/OS-II對任務(wù)棧的處理方法與缺陷</B></P>
<P
style="TEXT-INDENT: 30px">μC/OS-II為了保存任務(wù)堆棧中的數(shù)據(jù),對每個(gè)任務(wù)定義一個(gè)數(shù)組變量作為堆棧,在任務(wù)切換時(shí),將CPU堆棧指針SP指向該數(shù)組中的某個(gè)元素,即棧頂,如圖2所示。</P>
<P style="TEXT-INDENT: 30px">比如,在其ex21.c文件中定義的任務(wù)堆棧語句為:</P>
<P style="TEXT-INDENT: 30px">OS_STK TaskStartStk[TASK_STK_SIZE];
/*啟動任務(wù)堆棧*/</P>
<P style="TEXT-INDENT: 30px">OS_STK TaskClkStk[TASK_STK_SIZE];
/*時(shí)鐘任務(wù)堆棧*/</P>
<P style="TEXT-INDENT: 30px">OS_STK TasklStk[TASK_STK_SIZE];
/*任務(wù)1#,任務(wù)堆棧*/</P>
<P style="TEXT-INDENT: 30px">……</P>
<P
style="TEXT-INDENT: 30px">以上各任務(wù)堆棧數(shù)組變量在初始化函數(shù)OSTCBInit()中被會給了任務(wù)控制塊OS_TCB的OSTCBStkPtr變量。在任務(wù)切換時(shí),μC/OS-II調(diào)用OSCtxSw匯編過程(OS_CPU_A.ASM文件),將CPU的SP指針指向該變量,從而使每個(gè)任務(wù)使用獨(dú)立的任務(wù)堆棧。</P>
<P style="TEXT-INDENT: 30px">LES BX,DWORD PTR DS:_OSTCBCur</P>
<P style="TEXT-INDENT: 30px">;保存掛起任務(wù)的堆棧指針SP</P>
<P style="TEXT-INDENT: 30px">MOV ES:[BX+2],SS</P>
<P style="TEXT-INDENT: 30px">MOV ES:[BX+0],SP</P>
<P style="TEXT-INDENT: 30px">……</P>
<P style="TEXT-INDENT: 30px">LESB X,DWORD PTR DS:_OSTCBHighRdy
;切換SP到要運(yùn)行任務(wù)的堆??臻g</P>
<P style="TEXT-INDENT: 30px">MOV SS,ES:[BX+2]</P>
<P style="TEXT-INDENT: 30px">MOV SP,ES:[BX]</P>
<P style="TEXT-INDENT: 30px">……<BR><IMG height=279 hspace=1
src="——uC-OS-II任務(wù)棧處理的一種改進(jìn)方法.files/5b.gif" width=382 align=right
vspace=1 border=0><BR> <SPAN
class=main1>在代碼中,變量OSTCBHighRdy(OSTCBCur)和堆棧指針變量OSTCBStkPtr的數(shù)值是同同的,因?yàn)镺STCBStkPtr是結(jié)構(gòu)OSTCBHighRdy的第一個(gè)變量。</P>
<P
style="TEXT-INDENT: 30px">這種任務(wù)棧處理方法的缺點(diǎn)是可能造成空間的浪費(fèi)。因?yàn)橐粋€(gè)任務(wù)如果堆棧滿了,該任務(wù)也就無法運(yùn)行,即使其它任務(wù)的堆棧還有空間可用。當(dāng)然,這種方法的好處是任務(wù)棧切換的時(shí)間非常短,只需要幾條指令。</P>
<P style="TEXT-INDENT: 0px"><B>4 共用空間的堆棧處理方法</B></P>
<P style="TEXT-INDENT: 30px">(1)棧共用連續(xù)存儲空間</P>
<P
style="TEXT-INDENT: 30px">如果多個(gè)任務(wù)使用同一段連續(xù)空間作為堆棧,這樣各個(gè)堆棧之間就可以互補(bǔ)使用。在前面說過,共用空間的問題在于一個(gè)任務(wù)運(yùn)行時(shí)不能破壞其它任務(wù)的堆棧數(shù)據(jù)。為簡單起見,先看圖3所示兩個(gè)任務(wù)的情況。</P>
<P
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -