博客操作系統(tǒng)_第1頁
博客操作系統(tǒng)_第2頁
博客操作系統(tǒng)_第3頁
博客操作系統(tǒng)_第4頁
博客操作系統(tǒng)_第5頁
已閱讀5頁,還剩157頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

整些基本概念

什么是操作系統(tǒng)?

操作系統(tǒng)(OperatingSystem,OS)是一種基本系統(tǒng)軟件。它在計(jì)算機(jī)硬件和計(jì)算機(jī)應(yīng)用程序之間,通過提供應(yīng)用程序接口(ApplicationProgrammingInterface,API),屏蔽了計(jì)算機(jī)硬件工作的一些細(xì)節(jié),從而使應(yīng)用程序的設(shè)計(jì)人員得以在一個(gè)友好的平臺(tái)上進(jìn)行應(yīng)用程序的設(shè)計(jì)和開發(fā),大大提高了應(yīng)用程序的開發(fā)效率。操作系統(tǒng)的作用

操作系統(tǒng)為應(yīng)用程序提供一個(gè)界面友好,性能穩(wěn)定,安全,效率高,操作方便的虛擬計(jì)算機(jī)。操作系統(tǒng)的功能

1.處理器的管理

2.存儲(chǔ)的管理

3.設(shè)備的管理

4.文件的管理

5.網(wǎng)絡(luò)和通信的管理

6.提供用戶接口嵌入式系統(tǒng)

嵌入式系統(tǒng)是對(duì)對(duì)象進(jìn)行自動(dòng)控制而使其具有智能化并可嵌入對(duì)象體系中的專用計(jì)算機(jī)系統(tǒng)。嵌入式系統(tǒng)的特點(diǎn)

1.專用性強(qiáng)

2.可裁剪性好

3.實(shí)時(shí)性與可靠性好

4.功耗低嵌入式操作系統(tǒng)的特點(diǎn)

1.微型化

2.可裁剪性

3.實(shí)時(shí)性

4.高可靠性

5.易移植性實(shí)時(shí)操作系統(tǒng)

能使計(jì)算機(jī)系統(tǒng)及時(shí)響應(yīng)外部事件的請(qǐng)求,并能及時(shí)控制所有實(shí)施設(shè)備與實(shí)時(shí)任務(wù)協(xié)調(diào)運(yùn)行,且能在一個(gè)規(guī)定的時(shí)間內(nèi)完成對(duì)事件的處理。

實(shí)時(shí)操作系統(tǒng)需要滿足的條件

1.多任務(wù)系統(tǒng)

2.任務(wù)的切換時(shí)間與系統(tǒng)中的任務(wù)數(shù)無關(guān)

3.中斷延時(shí)的時(shí)間可預(yù)知并盡可能短ucos-ii

ucos-ii是由JeanJ.Labrosse于1992年編寫的一個(gè)嵌入式多任務(wù)實(shí)時(shí)操作系統(tǒng),最早這個(gè)系統(tǒng)叫做ucos,后來進(jìn)過10年的應(yīng)用和修改,被美國聯(lián)邦航空管理局認(rèn)證。

它構(gòu)思巧妙,結(jié)構(gòu)精煉,很適合初次接觸操作系統(tǒng)的人去學(xué)習(xí)并應(yīng)用。說點(diǎn)自己的初步感受

1.多任務(wù),比如以前用單片機(jī),一次幾乎只做一個(gè)任務(wù),有了操作系統(tǒng)可以做多個(gè)任務(wù),而且互不干擾。

2.使編程變的很方便,程序員只負(fù)責(zé)編寫任務(wù),對(duì)任務(wù)的管理交給操作系統(tǒng)去做。

3.效率高,比如以前常常用一個(gè)delay函數(shù)做一個(gè)延時(shí),但是現(xiàn)在可以把這個(gè)delay時(shí)間用于CPU執(zhí)行別的任務(wù),CPU就不會(huì)閑著沒事數(shù)數(shù)玩ucos創(chuàng)建任務(wù)

ucos的任務(wù)有5種狀態(tài):

1.休眠態(tài):任務(wù)駐留在內(nèi)存中,但并不被操作系統(tǒng)調(diào)度

2.就緒態(tài):任務(wù)已經(jīng)準(zhǔn)備好,可以運(yùn)行,但是由于比它優(yōu)先級(jí)更高的任務(wù)在運(yùn)行,所以它暫時(shí)還不能運(yùn)行

3.運(yùn)行態(tài):任務(wù)掌握了CPU的使用權(quán),正在運(yùn)行

4.掛起態(tài)(等待事件態(tài)):任務(wù)在等待某一事件(共享資源、信號(hào))的發(fā)生。

5.被中斷態(tài):任務(wù)被中斷,暫時(shí)得不到運(yùn)行。其轉(zhuǎn)換關(guān)系如下圖:

下面用VC做個(gè)試驗(yàn):

//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧voidTaskOne(void*p_arg);voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("TaskOne:我在運(yùn)行!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}

//***********************************************************************************運(yùn)行結(jié)果如下圖:

以上注意幾點(diǎn):

1.每個(gè)任務(wù)都要有一個(gè)合適大小的堆棧,并用OS_STK類型定義

2.main中基本步驟是OSInit()->任務(wù)、信號(hào)等的管理->OSStart()

3.任務(wù)要做成一個(gè)無限循環(huán)體

4.任務(wù)的延時(shí)要用ucos的延時(shí)函數(shù)OSTimeDlyHMSM或OSTimeDly,把CPU交出,誰也不能獨(dú)占嘛。

5.OSTaskCreateExt也可以創(chuàng)建任務(wù),功能更多。

6.此版本支持64個(gè)任務(wù)(目前最新的ucos支持256個(gè)任務(wù)),最低兩個(gè)任務(wù)為系統(tǒng)任務(wù),不要用,按作者的建議,優(yōu)先級(jí)最低4個(gè)和最高4個(gè)任務(wù)不要用。關(guān)于內(nèi)核的分析:1.任務(wù)在OSTaskCreate之前處于休眠態(tài),OSTaskCreate之后處于就緒態(tài),打印printf時(shí)明顯是運(yùn)行態(tài),OSTimeDlyHMSM后處于等待狀態(tài)。

2.OS_TCB是一個(gè)管理任務(wù)的結(jié)構(gòu)類型,每次創(chuàng)建任務(wù)后,OS會(huì)為該任務(wù)創(chuàng)建一個(gè)任務(wù)控制塊,該任務(wù)控制塊中的OSTCBPrio存放該任務(wù)的優(yōu)先級(jí)。

3.OS中有一個(gè)就緒表(INT8U)OSRdyTbl[8],記錄各個(gè)任務(wù)的就緒情況,每一個(gè)變量8位對(duì)應(yīng)8個(gè)任務(wù),代表一組,整個(gè)數(shù)組64位正好對(duì)應(yīng)64個(gè)任務(wù),置一為就緒。還有一個(gè)(INT8U)OSRdyGrp共8位,如果8組任務(wù)中只要某組中有就緒任務(wù),那么OSRdyGrp對(duì)應(yīng)位被置一。

4。登記就緒表:

OSRdyGrp|=OSMapTbl[prio>>3];

OSRdyTbl[prio>>3]|=OSMapTbl[prio&0x07];OSMapTbl是一個(gè)查找表,ucos為了加快速度,盡量用查找表的方法來處理數(shù)據(jù),這樣比普通的算法要快,但用費(fèi)些空間。INT8U

const

OSMapTbl[]

={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};按照這種方式:就緒表OSRdyTbl[8]和OSRdyGrp就被順利登記了,原理如下圖:

ucos任務(wù)的切換只要你會(huì)創(chuàng)建一個(gè)任務(wù),就會(huì)創(chuàng)建跟多的任務(wù),但要注意,每個(gè)任務(wù)必須有獨(dú)自的任務(wù)堆棧和優(yōu)先級(jí),還有每個(gè)任務(wù)必須有OS延時(shí)函數(shù),這樣才能在自己運(yùn)行過一次時(shí),把CPU讓給別的任務(wù),有福同享嘛。下面做個(gè)雙任務(wù)程序:

//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧

OS_STK

TaskTwoStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);

voidTaskTwo(void*p_arg);voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)8

OSTaskCreate(TaskTwo,

0

,&TaskTwoStack[TASK_STK_SIZE-1],

8

);

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("TaskOne:我在運(yùn)行!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}void

TaskTwo(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("

TaskTwo:我處在運(yùn)行中!\n");

//打印

OSTimeDlyHMSM(0,0,2,0);

//延時(shí)0小時(shí)0分2秒0毫秒

}

}

//***********************************************************************************運(yùn)行結(jié)果如下圖:

可以看出TaskOne和TaskTwo輪流運(yùn)行,由于TaskTwo延時(shí)是2秒,所以它運(yùn)行頻率是TaskOne的一半,每個(gè)任務(wù)必須有一個(gè)OSTimeDlyHMSM,以便在自己運(yùn)行一次后,把CPU讓給優(yōu)先級(jí)最高的就緒任務(wù)。如果不給延時(shí),只有這一個(gè)任務(wù)一直處于運(yùn)行中。

內(nèi)核分析:

1.當(dāng)前任務(wù)運(yùn)行OSTimeDlyHMSM后,它被移出任務(wù)就緒表://延時(shí)后處于等待狀態(tài)

if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0){

/*Delaycurrenttask

*/

OSRdyGrp&=~OSTCBCur->OSTCBBitY;

2.這種移出不是無限制的,它的任務(wù)控制塊中的OSTCBDly被賦值,值為延時(shí)大?。?/p>

OSTCBCur->OSTCBDly=ticks;

3.ucos每一個(gè)時(shí)間片(比如10ms)進(jìn)行OSTickISR(),執(zhí)行一次OSTimeTick,將每個(gè)等待任務(wù)的OSTCBDly減一,一旦到0,就把它放入任務(wù)就緒表:void

OSTimeTick(void):

ptcb=OSTCBList;

/*PointatfirstTCBinTCBlist

*/

while(ptcb->OSTCBPrio!=OS_IDLE_PRIO){

/*GothroughallTCBsinTCBlist

*/

OS_ENTER_CRITICAL();

if(ptcb->OSTCBDly!=0){

/*DelayedorwaitingforeventwithTO

*/

if(--ptcb->OSTCBDly==0){

/*Decrementnbroftickstoendofdelay

*/

if((ptcb->OSTCBStat&OS_STAT_SUSPEND)==OS_STAT_RDY){/*Istasksuspended?

*/

OSRdyGrp

|=ptcb->OSTCBBitY;/*No,

MaketaskR-to-R(timedout)*/

OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;

}else{

/*Yes,Leave1ticktoprevent...

*/

ptcb->OSTCBDly=1;

/*...loosingthetaskwhenthe...

*/

}

/*...suspensionisremoved.

*/

}

}

ptcb=ptcb->OSTCBNext;

/*PointatnextTCBinTCBlist

*/

4.OSTickISR()然后運(yùn)行OSIntExit,OSIntExit先找到最高優(yōu)先級(jí)的任務(wù),將其優(yōu)先級(jí)放入OSTCBHighRdy中:

OSIntExitY

=OSUnMapTbl[OSRdyGrp];

/*...andnotlocked.

*/

OSPrioHighRdy=(INT8U)((OSIntExitY<<3)+OSUnMapTbl[OSRdyTbl[OSIntExitY]]);

if(OSPrioHighRdy!=OSPrioCur){

/*NoCtxSwifcurrenttaskishighestrdy*/

OSTCBHighRdy

=OSTCBPrioTbl[OSPrioHighRdy];

OSCtxSwCtr++;

/*Keeptrackofthenumberofctxswitches*/

OSIntCtxSw();

/*Performinterruptlevelctxswitch

*/從就緒表中查找最高優(yōu)先級(jí)的任務(wù),用幾個(gè)循環(huán)就可以這樣,但作者并沒這樣做,作者用查找表的方式,極大的提高速度,表如下:INT8U

const

OSUnMapTbl[256]={

0,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x00to0x0F

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x10to0x1F

*/

5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x20to0x2F

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x30to0x3F

*/

6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x40to0x4F

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x50to0x5F

*/

5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x60to0x6F

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x70to0x7F

*/

7,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x80to0x8F

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0x90to0x9F

*/

5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0xA0to0xAF

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0xB0to0xBF

*/

6,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0xC0to0xCF

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0xD0to0xDF

*/

5,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0,

/*0xE0to0xEF

*/

4,0,1,0,2,0,1,0,3,0,1,0,2,0,1,0

/*0xF0to0xFF

*/

};

如果你看到表很困惑,不要著急,自己假設(shè)幾個(gè)任務(wù)處于就緒狀態(tài),然后按程序給出的方法查一下表,從這個(gè)過程中你會(huì)發(fā)現(xiàn)此表的內(nèi)涵。

5.OSIntExit再運(yùn)行OSIntCtxSw(),讓優(yōu)先級(jí)的就緒任務(wù)運(yùn)行,其實(shí)就是把當(dāng)前CPU的所有寄存器壓入當(dāng)前任務(wù)的堆棧,將最高優(yōu)先級(jí)的就緒任務(wù)的堆棧中的內(nèi)容填充CPU各個(gè)寄存器。

這樣每個(gè)任務(wù)就可以按你延時(shí)的方式,有條不紊的穿插運(yùn)行。ucos刪除任務(wù)

刪除任務(wù)并非真的刪除任務(wù)的代碼,而是將此任務(wù)回到休眠態(tài)。

其函數(shù)為OSTaskDel(?);

//?為該任務(wù)的優(yōu)先級(jí)先做個(gè)程序?qū)嶒?yàn)下:

//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧

OS_STK

TaskTwoStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧

OS_STK

TaskThreeStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);

voidTaskTwo(void*p_arg);

voidTaskThree(void*p_arg);voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)7

OSTaskCreate(TaskTwo,

0

,&TaskTwoStack[TASK_STK_SIZE-1],

7

);

//建立任務(wù)TaskThree,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)8

OSTaskCreate(TaskThree,

0

,&TaskThreeStack[TASK_STK_SIZE-1],

8

);

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

intx=0;

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

x++;

if(x==4)

{

OSTaskDel(7);

//優(yōu)先級(jí)代表任務(wù)

printf("TaskOne:我刪除了TaskTwo!\n");

//打印

}

if(x==8)

{

OSTaskDel(8);

//優(yōu)先級(jí)代表任務(wù)

printf("TaskOne:我刪除了TaskThree!\n");

//打印

}

printf("TaskOne:我在運(yùn)行!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}void

TaskTwo(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("

TaskTwo:運(yùn)行中我也!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分2秒0毫秒

}

}void

TaskThree(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("

TaskThree:我還在!\n");

//打印

OSTimeDlyHMSM(0,0,2,0);

//延時(shí)0小時(shí)0分2秒0毫秒

}

}

//***********************************************************************************

運(yùn)行結(jié)果如下圖:

OSTaskDel()內(nèi)核分析:

執(zhí)行OSTaskDel()后,系統(tǒng)將該任務(wù)從任務(wù)控制塊鏈表中刪除:

1.先從就緒表中刪除:

OSRdyTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX{

/*Maketasknotready

*/

OSRdyGrp&=~ptcb->OSTCBBitY;

2.然后從事件等待表中刪除:

pevent=ptcb->OSTCBEventPtr;

if(pevent!=(OS_EVENT*)0){

/*Iftaskiswaitingonevent

*/

if((pevent->OSEventTbl[ptcb->OSTCBY]&=~ptcb->OSTCBBitX)==0){/*...removetaskfrom*/

pevent->OSEventGrp&=~ptcb->OSTCBBitY;

/*...eventctrlblock*/

}

}

3.再從事件等待表中刪除:

pnode=ptcb->OSTCBFlagNode;

if(pnode!=(OS_FLAG_NODE*)0){

/*Iftaskiswaitingoneventflag

*/

OS_FlagUnlink(pnode);

/*Removefromwaitlist

*/

}

4.最后把任務(wù)從任務(wù)控制塊鏈表中刪除:

OSTCBPrioTbl[prio]=(OS_TCB*)0;

/*Clearoldpriorityentry

*/

if(ptcb->OSTCBPrev==(OS_TCB*)0){

/*RemovefromTCBchain

*/

ptcb->OSTCBNext->OSTCBPrev=(OS_TCB*)0;

OSTCBList

=ptcb->OSTCBNext;

}else{

ptcb->OSTCBPrev->OSTCBNext=ptcb->OSTCBNext;

ptcb->OSTCBNext->OSTCBPrev=ptcb->OSTCBPrev;

}

ptcb->OSTCBNext=OSTCBFreeList;

/*ReturnTCBtofreeTCBlist

*/

OSTCBFreeList

=ptcb;

其實(shí)這樣直接刪除任務(wù)是不對(duì)的,因?yàn)榭赡苣硞€(gè)任務(wù)還占有資源時(shí),你就把它刪除了,這個(gè)資源得不到釋放而丟失,這對(duì)操作系統(tǒng)來說是不行的。所以在刪除之前,應(yīng)該先提出申請(qǐng),如果系統(tǒng)同意了,才能把它刪除。測(cè)試程序如下:

//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧

OS_STK

TaskTwoStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧

OS_STK

TaskThreeStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);

voidTaskTwo(void*p_arg);

voidTaskThree(void*p_arg);voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)7

OSTaskCreate(TaskTwo,

0

,&TaskTwoStack[TASK_STK_SIZE-1],

7

);

//建立任務(wù)TaskThree,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)8

OSTaskCreate(TaskThree,

0

,&TaskThreeStack[TASK_STK_SIZE-1],

8

);

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

intx=0;

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

x++;

if(x==4)

{

printf("TaskOne:我要求刪除TaskTwo!\n");

//打印

if(OSTaskDelReq(7)==OS_NO_ERR)

{

OSTaskDel(7);

//優(yōu)先級(jí)代表任務(wù)

printf("TaskOne:我刪除了TaskTwo!\n");

//打印

}

else

{

printf("TaskOne:我現(xiàn)在還不能刪除TaskTwo!\n");

//打印

}

}

if(x==8)

{

printf("TaskOne:我要求刪除TaskThree!\n");

//打印

if(OSTaskDelReq(8)==OS_NO_ERR)

{

OSTaskDel(8);

//優(yōu)先級(jí)代表任務(wù)

printf("TaskOne:我刪除了TaskThree!\n");

//打印

}

else

{

printf("TaskOne:我現(xiàn)在還不能刪除TaskThree!\n");

//打印

}

}

if(x==10)

{

printf("TaskOne:我要求刪除自己!\n");

//打印

if(OSTaskDelReq(6)==OS_NO_ERR)

//刪除自己還可以用OS_PRIO_SELF作為參數(shù)

{

OSTaskDel(6);

//優(yōu)先級(jí)代表任務(wù)

printf("TaskOne:我刪除了我自己!\n");

//打印

}

else

{

printf("TaskOne:沒人聽得見我說話了……!\n");

//打印

}

}

printf("TaskOne:我在運(yùn)行!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}void

TaskTwo(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("

TaskTwo:運(yùn)行中我也!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分2秒0毫秒

}

}void

TaskThree(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("

TaskThree:我思故我在!\n");

//打印

OSTimeDlyHMSM(0,0,2,0);

//延時(shí)0小時(shí)0分2秒0毫秒

}

}

//***********************************************************************************結(jié)果如下圖:

由于此程序中每個(gè)任務(wù)未用到資源,所以沒出現(xiàn)刪除請(qǐng)求被拒絕的情況。OSTaskDelReq()內(nèi)核分析:OSTaskDelReq()查看該任務(wù)的各種情況,如果遇到某種刪除不適情況,將其返回:INT8U

OSTaskDelReq(INT8Uprio)

{

#ifOS_CRITICAL_METHOD==3

/*AllocatestorageforCPUstatusregister

*/

OS_CPU_SR

cpu_sr;

#endif

BOOLEAN

stat;

INT8U

err;

OS_TCB

*ptcb;

#ifOS_ARG_CHK_EN>0

if(prio==OS_IDLE_PRIO){

/*Notallowedtodeleteidletask

*/

return(OS_TASK_DEL_IDLE);

}

if(prio>=OS_LOWEST_PRIO&&prio!=OS_PRIO_SELF){

/*Taskpriorityvalid?

*/

return(OS_PRIO_INVALID);

}

#endif

if(prio==OS_PRIO_SELF){

/*Seeifataskisrequestingto...

*/

OS_ENTER_CRITICAL();

/*...thistasktodeleteitself

*/

stat=OSTCBCur->OSTCBDelReq;

/*Returnrequeststatustocaller

*/

OS_EXIT_CRITICAL();

return(stat);

}

OS_ENTER_CRITICAL();

ptcb=OSTCBPrioTbl[prio];

if(ptcb!=(OS_TCB*)0){

/*Tasktodeletemustexist

*/

ptcb->OSTCBDelReq=OS_TASK_DEL_REQ;

/*SetflagindicatingtasktobeDEL.*/

err

=OS_NO_ERR;

}else{

err

=OS_TASK_NOT_EXIST;

/*Taskmustbedeleted

*/

}

OS_EXIT_CRITICAL();

return(err);

}

#endifucos任務(wù)的掛起和恢復(fù)

任務(wù)的掛起OSTaskSuspend()是將一個(gè)就緒任務(wù)轉(zhuǎn)換為等待任務(wù),任務(wù)的恢復(fù)是將一個(gè)等待任務(wù)。做個(gè)程序?qū)嶒?yàn)下:

//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧

OS_STK

TaskTwoStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);

voidTaskTwo(void*p_arg);voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)7

OSTaskCreate(TaskTwo,

0

,&TaskTwoStack[TASK_STK_SIZE-1],

7

);

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

intx=0;

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

x++;

if(x==4)

{

if(OSTaskSuspend(7)==OS_NO_ERR)

printf("TaskOne:我掛起了TaskTwo!\n");

//打印

else

printf("TaskOne:我沒能掛起TaskTwo!\n");

//打印

}

if(x==8)

{

if(OSTaskResume(7)==OS_NO_ERR)

printf("TaskOne:我恢復(fù)了TaskTwo!\n");

//打印

else

printf("TaskOne:我沒能恢復(fù)TaskTwo!\n");

//打印

}

printf("TaskOne:我在運(yùn)行!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}void

TaskTwo(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

printf("

TaskTwo:我在運(yùn)行!\n");

//打印

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分2秒0毫秒

}

}

//***********************************************************************************運(yùn)行結(jié)果如下:

內(nèi)核分析:

1.OSTaskSuspend(X)將優(yōu)先級(jí)為X的任務(wù)移出就緒表,并將此任務(wù)的狀態(tài)設(shè)置為掛起狀態(tài):

y

=ptcb->OSTCBY;

OSRdyTbl[y]&=~ptcb->OSTCBBitX;

/*Maketasknotready

*/

if(OSRdyTbl[y]==0){

OSRdyGrp&=~ptcb->OSTCBBitY;

}

ptcb->OSTCBStat|=OS_STAT_SUSPEND;

/*Statusoftaskis'SUSPENDED'

*/

2.OSTaskResume()將任務(wù)恢復(fù)(即取消掛起狀態(tài)),如果該任務(wù)不在延時(shí),那么放入就緒表中:

if(((ptcb->OSTCBStat&=~OS_STAT_SUSPEND)==OS_STAT_RDY)&&

/*Removesuspension

*/

(ptcb->OSTCBDly

==0)){

/*Mustnotbedelayed

*/

OSRdyGrp

|=ptcb->OSTCBBitY;

/*Maketaskreadytorun

*/

OSRdyTbl[ptcb->OSTCBY]|=ptcb->OSTCBBitX;

可以掛起當(dāng)前任務(wù),而且方便起見可以用OS_PRIO_SELF作為優(yōu)先級(jí)參數(shù)。ucos初始化和啟動(dòng)

一、ucos的初始化:OSInit()

在使用ucos的所有服務(wù)之前,必須調(diào)用OSInit(),對(duì)ucos自身的運(yùn)行環(huán)境進(jìn)行初始化。OSInit()運(yùn)行如下函數(shù):1.OS_InitMisc()

初始化一些全局變量:

OSTime

=0L

系統(tǒng)當(dāng)前時(shí)間(節(jié)拍數(shù))

OSIntNesting

=0

中斷嵌套的層數(shù)

OSLockNesting=0

調(diào)用OSSchededLock的嵌套層數(shù)

OSTaskCtr

=0

已建立的任務(wù)數(shù)

OSRunning

=FALSE

判斷系統(tǒng)是否正在運(yùn)行的標(biāo)志

OSCtxSwCtr

=0

上下文切換的次數(shù)

OSIdleCtr

=0L

空閑任務(wù)計(jì)數(shù)器

OSIdleCtrRun

=0L

空閑任務(wù)每秒的計(jì)數(shù)值

OSIdleCtrMax

=0L

空閑任務(wù)每秒計(jì)數(shù)的最大值

OSStatRdy

=FALSE

統(tǒng)計(jì)任務(wù)是否就緒2.OS_InitRdyList()

將就緒表及相關(guān)變量清03.OS_InitTCBList()

建立任務(wù)控制塊TCB鏈表,OSTCBList用于指向這個(gè)鏈表,鏈表中的每個(gè)結(jié)點(diǎn)存放每個(gè)任務(wù)的信息(優(yōu)先級(jí)、堆棧指針等)。

OSTCBPrioTbl[]是一個(gè)指針數(shù)組,指向每個(gè)任務(wù)結(jié)點(diǎn),方便快速定位。

如下圖:

4.OS_InitEventList()

建立事件控制塊ECB鏈表,鏈表中的每個(gè)結(jié)點(diǎn)存放每個(gè)事件的類型(信號(hào)量、互斥量等),計(jì)數(shù)、等待任務(wù)表等。

5.OS_FlagInit

事件標(biāo)志初始化6.OS_MemInit

內(nèi)存初始化

7.OS_QInit

郵箱初始化

8.OS_InitTaskIdle

建立空閑任務(wù),該任務(wù)必須建立,即系統(tǒng)必須至少有一個(gè)任務(wù)運(yùn)行,該任務(wù)只做簡單的計(jì)數(shù)工作。9.OS_InitTaskStat

建立統(tǒng)計(jì)任務(wù),可選(OS_TASK_STAT_EN>0),用于計(jì)算當(dāng)前CPU利用率。*

OSIdleCtr

*

CPUUsage(%)=100*(

1

-

------------

)

*

OSIdleCtrMax

二、多任務(wù)的啟動(dòng):OSStart()

void

OSStart(void)

{

INT8Uy;

INT8Ux;

if(OSRunning==FALSE){

y

=OSUnMapTbl[OSRdyGrp];

/*Findhighestpriority'staskprioritynumber

*/

x

=OSUnMapTbl[OSRdyTbl[y]];

OSPrioHighRdy=(INT8U)((y<<3)+x);

OSPrioCur

=OSPrioHighRdy;

OSTCBHighRdy

=OSTCBPrioTbl[OSPrioHighRdy];/*Pointtohighestprioritytaskreadytorun

*/

OSTCBCur

=OSTCBHighRdy;

OSStartHighRdy();

/*Executetargetspecificcodetostarttask

*/

}

}

找到優(yōu)先級(jí)最高的就緒任務(wù),標(biāo)記及運(yùn)行。OSStartHighRdy()就是運(yùn)行優(yōu)先級(jí)最高的就緒任務(wù),這個(gè)函數(shù)實(shí)際上是用匯編語言寫的,即用該任務(wù)的內(nèi)容填充CPU寄存器。ucos事件控制塊及處理函數(shù)

一.時(shí)間控制塊ECB的數(shù)據(jù)結(jié)構(gòu)

typedefstruct{

INT8U

OSEventType;

/*Typeofeventcontrolblock(seeOS_EVENT_TYPE_???)

*/

INT8U

OSEventGrp;

/*Groupcorrespondingtotaskswaitingforeventtooccur

*/

INT16U

OSEventCnt;

/*SemaphoreCount(notusedifotherEVENTtype)

*/

void

*OSEventPtr;

/*Pointertomessageorqueuestructure

*/

INT8U

OSEventTbl[OS_EVENT_TBL_SIZE];/*Listoftaskswaitingforeventtooccur

*/

}OS_EVENT;.OSEventType

ECB類型

有以下幾種:

#define

OS_EVENT_TYPE_UNUSED

0

#define

OS_EVENT_TYPE_MBOX

1

#define

OS_EVENT_TYPE_Q

2

#define

OS_EVENT_TYPE_SEM

3

#define

OS_EVENT_TYPE_MUTEX

4

#define

OS_EVENT_TYPE_FLAG

5

.OSEventCnt

信號(hào)量計(jì)數(shù)

表示最大空共享的數(shù)目

.*OSEventPtr

用于消息和隊(duì)列

.OSEventTbl[]和.OSEventGrp

分別與管理任務(wù)的OSRdyTbl[]和OSRdyGrp類似,OSEventTbl[]用于放置該事件的所有等待任務(wù)。原理圖如下:

二、將任務(wù)置于等待事件的任務(wù)列表

pevent->OSEventGrp|=OSMapTbl[prio>>3];

pevent->OSEventTbl[prio>>3]|=OSMapTbl[prio&0x07];三、從等待任務(wù)列表中刪除一個(gè)任務(wù)

if((pevent->OSEventTbl[prio>>3]&=~OSMapTbl[prio&0x07])==0){

pevent->OSEventGrp&=~OSMapTbl[prio>>3];

}

四、在等待任務(wù)列表中查找最高優(yōu)先級(jí)的任務(wù)

y=OSUnMapTbl[pevent->OSEventGrp];

x=OSUnMapTbl[pevent->OSEventTbl[y]];

prio=(y<<3)+x;

五、空余事件控制塊鏈表

在調(diào)用OSInit()時(shí),所有事件控制塊被鏈接成一個(gè)單向鏈表——空閑事件控制塊鏈表。每當(dāng)建立一個(gè)信號(hào)量、郵箱或者消息隊(duì)列時(shí),就從該鏈表中取出一個(gè)空閑事件控制塊,并對(duì)它進(jìn)行初始化。刪除時(shí),可將事件控制塊放回到空余事件控制塊鏈表中。

六、初始化一個(gè)事件控制塊,OS_EventWaitListInit()

就是將該ECB中的.OSEventTbl[]和.OSEventGrp全部清0

七、使一個(gè)任務(wù)進(jìn)入就緒態(tài),OS_EventTaskRdy()

先從等待任務(wù)列表中刪除這個(gè)任務(wù):

if((pevent->OSEventTbl[y]&=~bitx)==0x00){

/*Removethistaskfromthewaitinglist

*/

pevent->OSEventGrp&=~bity;

/*Clrgroupbitifthiswasonlytaskpending

*/

}

再將這個(gè)任務(wù)置于任務(wù)就緒表:

if(ptcb->OSTCBStat==OS_STAT_RDY){

/*Seeiftaskisready(couldbesusp'd)

*/

OSRdyGrp

|=

bity;

/*Puttaskinthereadytorunlist

*/

OSRdyTbl[y]

|=

bitx;

}

八、使一個(gè)任務(wù)進(jìn)入等待某事件發(fā)生狀態(tài),OS_EventTaskWait()

將任務(wù)移出就緒表

if((OSRdyTbl[OSTCBCur->OSTCBY]&=~OSTCBCur->OSTCBBitX)==0x00){

/*Tasknolongerready

*/

OSRdyGrp&=~OSTCBCur->OSTCBBitY;

/*Cleareventgrpbitifthiswasonlytaskpending

*/

}

將任務(wù)進(jìn)入該事件的等待列表

pevent->OSEventTbl[OSTCBCur->OSTCBY]|=OSTCBCur->OSTCBBitX;

/*Puttaskinwaitinglist

*/

pevent->OSEventGrp

|=OSTCBCur->OSTCBBitY;

有了這些基本知識(shí),后面的事件處理就簡單多了ucos

信號(hào)量

信號(hào)量是一類事件,用來標(biāo)志資源被占用的情況,當(dāng)任務(wù)在使用資源之前,應(yīng)對(duì)信號(hào)量進(jìn)行查詢,以了解資源的被占用情況,從而決定下一步行為。

如果沒有信號(hào)量,任務(wù)對(duì)資源的使用將發(fā)生混亂。下面的程序中兩個(gè)任務(wù)依靠一個(gè)字符變量card傳遞信息,因?yàn)闆]有使用信號(hào)量,所以信息沒有被正確的接收。//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧

OS_STK

TaskTwoStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);

voidTaskTwo(void*p_arg);charcard;//TaskOne每次利用card向TaskTwo發(fā)一個(gè)字符,card作為共享資源voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)7

OSTaskCreate(TaskTwo,

0

,&TaskTwoStack[TASK_STK_SIZE-1],

7

);

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

charstr[]="Iloveyou!";

char*p=str;

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

card=*p;

if(card!='\0')

{

printf("TaskOne:%c

\n",card);

//打印

p++;

}

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}void

TaskTwo(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

if(card!='\0')

printf("

TaskTwo:%c

\n",card);

OSTimeDlyHMSM(0,0,1,345);

//延時(shí)0小時(shí)0分1秒345毫秒

}

}

//***********************************************************************************運(yùn)行結(jié)果如下:

TaskOne發(fā)出:"Iloveyou!",但是TaskTwo收到的是"Ilveou!"。

為了克服這個(gè)占用資源混亂的問題,這里使用信號(hào)量,它就像一把鑰匙,只有拿到鑰匙的人才能使用相應(yīng)的資源,使用完資源后需要后,需要釋放這把鑰匙給別人用。鑰匙的數(shù)量(信號(hào)量計(jì)數(shù))可以設(shè)定,這里設(shè)置為1,即二值信號(hào)量,任一時(shí)刻只能有一個(gè)任務(wù)持有該鑰匙。下面是這個(gè)實(shí)驗(yàn)程序:

//***********************************************************************************

#include<includes.h>#define

TASK_STK_SIZE

128

//定義任務(wù)堆棧的大小OS_STK

TaskOneStack[TASK_STK_SIZE];

//為任務(wù)TaskOne建立一個(gè)堆棧

OS_STK

TaskTwoStack[TASK_STK_SIZE];

//為任務(wù)TaskTwo建立一個(gè)堆棧voidTaskOne(void*p_arg);

voidTaskTwo(void*p_arg);OS_EVENT*key;

//事件控制塊指針

charcard;

//TaskOne每次利用card向TaskTwo發(fā)一個(gè)字符,card作為共享資源

charerr;

//錯(cuò)誤信息voidmain(void)

{

OSInit();

//初始化ucos

//建立任務(wù)TaskOne,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)6

OSTaskCreate(TaskOne,

0

,&TaskOneStack[TASK_STK_SIZE-1],

6

);

//建立任務(wù)TaskTwo,無數(shù)據(jù)區(qū)指針,

堆棧指針,

優(yōu)先級(jí)7

OSTaskCreate(TaskTwo,

0

,&TaskTwoStack[TASK_STK_SIZE-1],

7

);

key=OSSemCreate(1);

//建立一個(gè)信號(hào)量,允許共享數(shù)為1,該控制塊的地址給key

OSStart();

//開始運(yùn)行ucos

}

void

TaskOne(void*p_arg)

{

charstr[]="Iloveyou!";

char*p=str;

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

OSSemPend(key,0,&err);

//申請(qǐng)信號(hào)量key,延時(shí)為無限長(0)

card=*p;

if(card!='\0')

{

printf("TaskOne:%c

\n",card);

//打印

p++;

}

OSTimeDlyHMSM(0,0,1,0);

//延時(shí)0小時(shí)0分1秒0毫秒

}

}void

TaskTwo(void*p_arg)

{

p_arg=p_arg;

//無用,僅為消除編譯器報(bào)警

while(1)

//任務(wù)體,總是死循環(huán)

{

if(card!='\0')

printf("

TaskTwo:%c

\n",card);

OSSemPost(key);

//釋放信號(hào)量key

OSTimeDlyHMSM(0,0,1,345);

//延時(shí)0小時(shí)0分1秒345毫秒

}

}

//***********************************************************************************運(yùn)行結(jié)果如下圖:

可見,TaskOne要說的話通過全局字符變量card順利傳遞給TaskTwo。

內(nèi)核分析:

1.OSSemCreate()先將空余事件控制塊鏈表的指針向后推進(jìn)一結(jié)

if(OSEventFreeList!=(OS_EVENT*)0){

/*SeeifpooloffreeECBpoolwasempty

*/

OSEventFreeList=(OS_EVENT*)OSEventFreeList->OSEventPtr;

}在將這個(gè)留出結(jié)點(diǎn)用所創(chuàng)造的信號(hào)量去填充

pevent->OSEventType=OS_EVENT_TYPE_SEM;

pevent->OSEventCnt

=cnt;

/*Setsemaphorevalue

*/

pevent->OSEventPtr

=(void*)0;

/*UnlinkfromECBfreelist

*/

OS_EventWaitListInit(pevent);

/*Initializeto'nobodywaiting'onsem.

*/

2.等待一個(gè)信號(hào)量,OSSemPend()將pevent->OSEventCnt減一,表示已經(jīng)有一個(gè)任務(wù)去占用它:

pevent->OSEventCnt--;任務(wù)狀態(tài)設(shè)置:OSTCBCur->OSTCBStat|=OS_STAT_SEM;將任務(wù)置于該ECB的等待列表

OS_EventTaskWait(pevent);

/*Suspendtaskuntileventortimeoutoccurs

*/

3.發(fā)出一個(gè)信號(hào)量,OSSemPost()使當(dāng)前任務(wù)移出該ECB的等待列表,并進(jìn)入就緒態(tài):OS_EventTaskRdy()讓出信號(hào)量

:pevent->OSEventCnt++;ucos移植前的準(zhǔn)備——自己寫一個(gè)調(diào)度的系統(tǒng)(一)2011-09-1710:24現(xiàn)在想把ucos的移植經(jīng)驗(yàn)分享給大家,如果你沒有基礎(chǔ),建議先別急于移植,因?yàn)槟悴幻靼渍{(diào)度的原理,即使是模仿別人的方法,如果寫錯(cuò)一條匯編指令,系統(tǒng)也會(huì)崩潰,你也始終找不到頭緒。

所以在移植之前,1.你要會(huì)使用ucos,即在ucos下編程。2.熟悉調(diào)度的原理,能夠獨(dú)立編寫任務(wù)調(diào)度程序。

只有會(huì)這兩點(diǎn),移植ucos才可能。

前面已經(jīng)說了ucos下編程(雖然消息、郵箱等沒說,相信入門后

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論