當前位置:編程學習大全網 - 網絡軟體 - semm7

semm7

VxWorks下采用C++構建Application可以使得程序更加利於維護,利用其提供的STL支持,可以省去大量的底層工作,大大加速軟件的開發進度。

1 異常類VxError

首先封裝異常類VxError,當程序出現異常時,向外層調用者拋出壹個該類的對象,調用者采用try-catch clause捕獲該異常對象,進行異常處理。

由於該類針對的是系統運行時產生的異常,故考慮由C++標準異常類中的runtime_error類派生;VxWorks內核采用設置全局變量errno的方式記錄系統運行中產生的錯誤,所以將int ?errNum 作為該類的成員變量,用以記錄異常發生時的errno值。源代碼如下:

#include?<stdexcept>

#include?"errnoLib.h"

class?VxRunTimeError?:?public?runtime_error?{

protected:

int?errNum;

public:

VxRunTimeError(const?string?msg?=?"")?:?runtime_error(msg),?errNum(errnoGet?())

{

}

int?getErrNum(void)

{

return?errNum;

}

};

2 任務類VxTask

任務類VxTask用以封裝VxWorks的task,本來考慮將任務的入口函數作為該類的純虛成員函數,用戶只要在該類的派生類中重載該純虛函數就能實現自己的VxWorks task,但由於taskSpawn()的入口函數的參數類型是FUNCPTR(typedef ?int (*FUNCPTR) (...)),而指向VxTask類成員函數的指針類型為int (VxTask:: *ptr)(…),編譯器不支持這兩種類型之間的強制類型轉換,所以只能換種思路——用壹個名為Runnable的類專門封裝task的入口函數,同時提供壹個靜態成員函數完成對該入口函數的調用,而該靜態成員函數地址可以轉換成FUNCPTR類型,供taskSpawn()調用。在VxTask類中實現關於task的系統調用。部分源代碼如下:

class?Runnable?{

protected:

virtual?void?run()?=?0;

public:

static?void?entry(Runnable?*?Run)

{

Run->run();

}

virtual?~Runnable()

{

}

};

class?VxTask?{

protected:

char?*name;

int?tid;

public:

VxTask(char*?Name,?int?Arg1?,?FUNCPTR?Entry?=?(FUNCPTR)Runnable::entry,?int?Pri?=?150,?int?Opt?=?VX_FP_TASK,?int?StackSize?=?2000000,

int?Arg2?=?0,?int?Arg3?=?0,?int?Arg4?=?0,?int?Arg5?=?0,?int?Arg6?=?0,?int?Arg7?=?0,?int?Arg8?=?0,?int?Arg9?=?0,?int?Arg10?=?0)?:?name(Name)

{

if(Entry?==?NULL)?{

throw(VxRunTimeError("Task?Creat?Fail:?Entry?Can't?be?NULL!"));

}

tid=taskSpawn(Name,Pri,Opt,StackSize,Entry,Arg1,Arg2,?Arg3,Arg4,Arg5,Arg6,Arg7,Arg8,Arg9,Arg10);

if(tid?==?ERROR)?{

throw(VxRunTimeError("Task?Spawn?Fail!"));

}

}

~VxTask()

{

if(taskDelete(tid)?==?ERROR)?{

throw(VxRunTimeError("Task?Delete?Error:?Task?delete?fail!"));

}

}

void?suspend()

{

if(taskSuspend(tid)?==?ERROR)?{

throw(VxRunTimeError("Task?Suspend?Error:?Task?suspend?fail!"));

}

}

void?resume()

{

if(taskResume(tid)?==?ERROR)?{

throw(VxRunTimeError("Task?Resume?Error:?Task?resume?fail!"));

}

}

int?getTid()

{

return?tid;

}

};

使用時首先派生Runnable的子類,重載其run()成員函數,然後將該子類的對象指針賦給VxTask的構造函數,用戶task就跑起來了:

class?MyRunnable?:?public?Runnable

{

void?run()?{

while(1)?{

cout<<"Hello?VxWorks?Task?World!"<<endl;

taskDelay(sysClkRateGet());

}

}

};

void?myMain()

{

MyRunnable?myRun;

VxTask?task(“tMyRun”,?(int)&myRun);

While(1)?{

taskDelay(sysClkRateGet());

}

}

在shell中sp myMain可以看到預期效果,但如果myMain()中去掉最後的while(1)循環,就只會在輸出窗口中看壹次Hello VxWorks Task World!輸出。Why?(提示:VxTask的析構函數!)

3 中斷類VxInt

中斷類VxInt與VxTask類似,同樣用Runnable的派生類封裝入口函數,VxInt類實現中斷系統調用:

typedefvoid?(**VOIDFUNCPTRPTR)?(...);

class?VxInt?{

protected:

int?intNum;

public:

VxInt(int?IntNum,?int?Arg?=?0,?VOIDFUNCPTR?Entry?=?(VOIDFUNCPTR)Runnable::entry)?:?intNum(IntNum)

{

if(intConnect((VOIDFUNCPTRPTR)INUM_TO_IVEC(intNum),?Entry,?Arg)?==?ERROR)?{

throw(VxRunTimeError("Interrupt?Connect?Fail!"));

}

}

};

與task不同,中斷服務程序(ISR)中不能調用可能被阻塞的函數,這點需要在重載Runnable派生類中的run()成員函數時引起註意。

4 看門狗類 VxWatchDog

VxWorks中的看門狗實際上是利用系統時鐘中斷來定時執行某個函數的,所以被看門狗執行的函數是運行在中斷的上下文(Context)中,而不是任務的上下文中,故該函數中也不能調用帶有阻塞功能的函數。所以VxWatchDog的實現與中斷類VxInt類似:

class?VxWatchDog?{

WDOG_ID?id;

int?delay;

public:

VxWatchDog(int?Delay,?Runnable?*EntryObj)?:?delay(Delay)

{

id?=?wdCreate();

if(id?==?NULL)?{

throw(VxRunTimeError("Watch?Dog?Creat?Fail!"));

}

if(wdStart(id,?delay,?(FUNCPTR)Runnable::entry,(int)EntryObj)?!=?OK)?{

throw(VxRunTimeError("Watch?Dog?Start?Fail!"));

}

}

void?cancel()

{

if(wdCancel(id)?!=?OK)?{

throw(VxRunTimeError("Watch?Dog?Cancel?Fail!"));

}

}

WDOG_ID?getId()

{

return(id);

}

~VxWatchDog()

{

if(wdDelete(id)?!=?OK)?{

throw(VxRunTimeError("Watch?Dog?Delete?Fail!"));

}

}

};

wdStart(WDOG_ID Id, int Delay, FUNCPTR Ptr, int Para )只會讓函數Ptr在延時Delay ticks後執行壹次,要周期性地執行Ptr,需要在Ptr中遞歸調用wdStart()。那能否這樣實現呢:

class?WdRun?:?public?Runnable?{

protected:

void?run()?{

logMsg("Hello?Watch?Dog?World!",0,0,0,0,0,0);

VxWatchDog?wtDog(sysClkRateGet(),?this);

}

};

上述程序試圖在入口函數中產生壹個VxWatchDog類的對象,並用this指針初始化該對象,以期達到每秒鐘執行壹次入口函數的目的。但是不要忘了該入口函數是運行在中斷的上下文中的,不允許動態地產生或刪除對象,所以采用這種方法實現周期性執行作業並不可行。

為了在入口函數中調用wdStart(),且要避免動態地生成VxWatchDog對象,需要在Runnable派生類的成員變量中包含壹個VxWatchDog指針,通過該指針調用所指對象的wdStart()。為此,需要在VxWatchDog類中增加成員函數:

VxWatchDog?::VxWatchDog(int?Delay)?:?id(wdCreate()),?delay(Delay)

{

if(id?==?NULL)?{

throw(VxRunTimeError("Watch?Dog?Creat?Fail!"));

}

}

void?VxWatchDog?::start(Runnable?*EntryObj)

{

if(wdStart(id,?delay,?(FUNCPTR)Runnable::entry,?(int)EntryObj)?!=?OK)?{

throw(VxRunTimeError("Watch?Dog?Start?Fail!"));

}

}

class?WdRun?:?public?Runnable?{

protected:

VxWatchDog?*dog;

virtual?void?run()?{

logMsg("Hello?Watch?Dog?World!",0,0,0,0,0,0);

dog->start(this);

}

public:

WdRun(VxWatchDog?*Dog)?:?dog(Dog)

{

}

};

void?myMain()

{

VxWatchDog?wtDog(sysClkRateGet());

WdRun?run(&wtDog);

wtDog.start(&run);

while(1)?{

taskDelay(sysClkRateGet());

cout<<"In?Main!"<<endl;

}

}

在shell中輸入sp myMain,可以看到預期輸出。

5 信號量類 VxSem

VxWorks信號量包括互斥信號量、二進制信號量和計數信號量,這三種信號量除了創建時調用各自的創建函數,其它操作具有相同的接口,所以考慮采用VxSem類作為信號量基類,提供統壹的信號量操作接口,VxSemM、VxSemB、VxSemC三個派生類分別封裝了三種信號量的創建函數:

class?VxSem?{

protected:

SEM_ID?id;

public:

VxSem(SEM_ID?Id)?:?id(Id)

{

}

virtual?~VxSem()

{

if(semDelete(id)?==?ERROR)?{

throw(VxRunTimeError("Semaphore?Delete?Fail!"));

}

}

void?take(int?TimeOut?=?WAIT_FOREVER)

{

if(semTake(id,WAIT_FOREVER)?==?ERROR)?{

throw(VxRunTimeError("Semaphore?Take?Fail!"));

}

}

void?give()

{

if(semGive(id)?==?ERROR)?{

throw(VxRunTimeError("Semaphore?Give?Fail!"));

}

}

void?flush()

{

if(semFlush(id)?==?ERROR)?{

throw(VxRunTimeError("Semaphore?Flush?Fail!"));

}

}

SEM_ID?getId()

{

return?id;

}

};

class?VxSemB?:?public?VxSem?{

public:

VxSemB(int?Opts?=?SEM_Q_FIFO,?SEM_B_STATE?State?=?SEM_EMPTY)?:?VxSem(semBCreate?(Opts,?State))

{

if(id?==?0)?{

throw(VxRunTimeError("Binary?Semaphore?Creat?Fail!"));

}

}

};

class?VxSemM?:?public?VxSem?{

public:

VxSemM(int?Opts?=?SEM_Q_PRIORITY?|?SEM_INVERSION_SAFE?|?SEM_DELETE_SAFE)?:?VxSem(semMCreate?(Opts))

{

if(id?==?0)?{

throw(VxRunTimeError("Mutual-exclusion?Semaphore?Creat?Fail!"));

}

}

};

class?VxSemC?:?public?VxSem?{

public:

VxSemC(int?Opts,?int?Cnt)?:?VxSem(semCCreate?(Opts,?Cnt))

{

if(id?==?0)?{

throw(VxRunTimeError("Counting?Semaphore?Creat?Fail!"));

}

}

};

  • 上一篇:淘寶的直播人數怎麽刷啊?有用嗎
  • 下一篇:妳只屬於我怎麽幽默回復
  • copyright 2024編程學習大全網