VxWorks程序指南 分類: vxWorks 2014-03-13 08:56 502人閱讀 評論(0) 收藏

*******************************************
1、任務
*******************************************
任務狀態:掛起、阻塞、就緒、睡眠。
任務能夠在任何一種狀態被刪除。
Wind內核裏有256種優先級,0最高,255爲最低。
任務調度控制函數
kernelTimeSlice() 控制輪轉調度
taskPrioritySet() 改變任務優先級
taskLock()    禁止任務調度
taskUnlock()   容許任務調度
ios

當任務訪問一個可能會被中斷服務程序訪問的變量或者數據結構時,可使用intLock()實現互斥。
經過taskLock()、taskUnlock()搶佔上鎖可禁止優先級的搶佔,中斷服務程序仍然能夠執行。
全部應用任務的優先級應該在100-250之間;可是驅動程序支持的任務(與中斷服務程序關聯的任務)優先級可以位於51-99。
任務堆棧的空間分配:爲了不堆棧溢出和破壞任務堆棧可以使用下列方法:
在最初分配堆棧空間時,分配比預先估計大一些的空間;而後週期性地調用checkStack()函數監控;若能夠安全使用更小的空間,將修改分配空間的尺寸。
通常vxWorks使用任務ID號來定位任務,約定ID號爲0的表示任務調用。
vxWorks操做系統不須要唯一的任務名,但爲了不混亂,建議使用唯一的任務名。
vxWorks操做系統的任務命名規則:全部從目標機啓動的任務以字母t開頭,而從主機啓動的任務以字母u開頭。
算法

任務建立函數
taskSpawn()   建立並激活一個新任務
taskInit()    初始化一個新任務
taskActivate()激活一個初始化任務
任務名和ID函數
taskName()    獲得與任務號相關的任務名
taskNameToId()尋找與任務名相關的任務ID
taskIdSelf()  得到調用任務的ID號
taskIdVerify()檢查一個特定任務的存在性
在任務建立時,若需執行下列操做則要包括VX_FP_TASK選項:
1實行浮點操做2調用返回浮點值的函數3調用以浮點值爲參數的函數
任務選項函數
taskOptionGet() 檢查任務選項
taskOptionSet() 設置任務選項 目前只有VX_UNBREAKABLE選項能夠被修改
任務信息:因爲任務狀態是動態的,除非知道任務處於掛起,不然不能得到當前信息
taskIdListGet() 用ID填充一組全部激活的任務
taskInfoGet()   獲得任務的信息
taskPriorityGet() 查看任務的優先級
taskRegsGet()  檢查任務寄存器(不能使用單前任務時)
taskRegsSet()  設置任務寄存器(不能使用單前任務時)
taskIsSuspended()檢查任務是否處於掛起狀態
taskIsReady()  檢查任務是否處於就緒狀態
taskTcb()      得到任務控制塊的指針
任務刪除函數
exit()    終止任務調用,釋放內存
taskDelete()終止指定任務,釋放內存
taskSafe() 保護調用任務免於刪除
taskUnsafe() 解除任務刪除保護
shell

下面的代碼代表瞭如何使用taskSafe()函數和taskUnsafe()函數去保護一個臨界代碼區域
taskSafe();
semTake (semId,WAIT_FOREVER);/*阻塞直至信號量可用*/
.../*臨界區域代碼*/
semGive(semId); /*釋放信號量*/
taskUnsafe();
安全

任務控制函數
taskSuspend() 掛起任務,用來凍結任務狀態並進行檢查
taskResume()  恢復任務執行
taskRestart() 從新啓動任務
taskDelay()   延遲任務,延遲單位爲「tick」
nanosleep()   延遲任務,延遲單位爲納秒
服務器

下面的代碼無需考慮時鐘速率,將使任務延時半秒:
taskDelay(sysClkRateGet()/2);/*函數sysClkRateGet()返回系統時鐘的速率,單位tick/秒*/
taskDelay()函數把做爲調用者的任務移動到相同優先級隊列的尾部。
特別是,當調用taskDelay(0)時,將會把CPU交給系統中其餘相同優先級任務。
taskDelay(NO_WAIT);/*容許其餘相同優先級的任務運行*/
延時爲零時,只能調用taskDelay()函數,函數nanosleep()中的延時參數禁止爲零。
網絡

任務擴展函數
爲了容許其餘相關的任務函數加入到系統中去,vxWorks提供「hook」函數。該函數容許任務在建立
、刪除和上下文交換時調用附加的函數。
taskCreateHookAdd()  增長一個在每一個任務建立時都調用的函數
taskCreateHookDelete() 刪除一個之前加入的任務建立函數
taskSwitchHookAdd()  增長一個在每一個任務切換時都調用的函數
taskSwitchHookDelete() 刪除一個之前加入的任務切換函數
taskDeleteHookAdd()  增長一個在每一個任務被刪除時都調用的函數
taskDeleteHookDelete() 刪除一個之前加入的任務刪除函數
*******************************************
2、任務通訊
*******************************************
大部分vxWorks函數使用下列重入技術:1動態堆棧變量2被信號保護的全局和靜態變量2任務變量
在編寫被多個任務內務調用的應用代碼時,建議使用這些技術。
vxWorks的任務間通訊:
1共享內存,數據的簡單共享
2信號量,基本的互斥和同步
3Mutexe和條件變量,使用POSIX接口時互斥與同步操做
4消息隊列和管道,同一個CPU內任務間消息的傳遞
5sockets和遠程任務調用,任務間透明的網絡通訊
6信號,用於異常處理。
數據結構

信號量控制函數
semBCreate() 分配並初始化一個二進制信號量
semMCreate() 分配並初始化一個互斥信號量
semCCreate() 分配並初始化一個計數器信號量
semDelete()  終止並釋放一個信號量
semTake()    獲取一個信號量
semGive()    提供一個信號量
semFlush()   解鎖全部正在等待信號量的任務
異步

二進制信號量
使用二進制信號量可以知足兩種任務的協調須要:互斥和同步。
互斥的實現:
建立一個二進制信號量,初始可用(SEM_FULL)。
當任務訪問資源時,首先必須得到信號量。
只要任務持有信號量,其餘全部須要訪問該資源的任務將被阻塞。
#include "vxWorks.h"
#include "semLib.h"
SEM_ID semMutex;
semMutex = semBCreate(SEM_Q_PRIORITY,SEM_FULL);
...
semTake (semMutex,WAIT_FOREVER);
.../*臨界區域,任什麼時候候僅單個任務能夠訪問*/
semGive(semMutex);
同步的實現:
初始時信號量不可用(SEM_EMPTY)。
任務或中斷服務程序經過釋放信號量來代表事件的發生。
調用semTake()函數提取信號量的其餘任務處於等待狀態,直至事件發生,並釋放信號量。
#include "vxWorks.h"
#include "semLib.h"
#include "arch/arch/ivarch.h"/*用結構體類型代替arch*/
SEM_ID syncSem;
init(int someIntNum)
{
 /*鏈接中斷服務函數*/
 intConnect(INUM_TO_IVEC(someIntNum),evertInterruptSvcRout,0);
 /*創建信號量*/
 syncSem = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
 /*發起用於同步的任務*/
 taskSpawn("sample",100,0,20000,task1,0,0,0,0,0,0,0,0,0,0);
}
socket

task1(void)
{
 ...
 semTake(syncSem, WAIT_FOREVER);/*等待事件發生*/
 printf("task 1 got the semaphore\n");
 .../*啓動事件*/
}
eventInterruptSvcRout(void)
{
 ...
 semGive(syncSem);/*讓任務1啓動事件*/
 ...
}
函數

互斥信號量:
互斥信號量是一種用於解決內在互斥問題的特殊的二進制信號量,包括優先級倒置,刪除安區以及資源的遞歸訪問。
互斥信號量的基本行爲與二進制信號量一致,不一樣之處以下:
1它僅用於互斥2它僅能由提取它(即調用semTake())的任務釋放3不能在中斷服務程序中釋放4semFlush()函數操做非法。
當一個高優先級任務須要等待一段不肯定的時間,讓低優先級任務完成時(如低優先級經過信號量佔有高優先級任務須要的資源),
須要發生優先級倒置。
下例用優先級繼承算法建立了一個互斥信號量:
semId = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE);/*使用優先級繼承選項SEM_INVERSION_SAFE的信號量必須選擇優先級順序隊列*/
下例是爲防止應用臨界資源的任務被意外刪除的一個互斥信號量
semId = semMCreate(SEM_Q_FIFO | SEM_DELETE_SAFE);
計數信號量應用:計數信號量適用於保護多份複製的資源:如可使用一個初始值爲5的計數器信號量來協調5個磁帶驅動器工做。
Wind消息隊列控制
msgQCreate() 分配並初始化一個消息隊列
msgQDelete() 終止並釋放一個消息隊列
msgQSend() 向一個消息隊列發送消息
msgQReceive() 從一個消息隊列接收消息
/* In this example, task t1 creates the message queue and sends a message
 * to task t2. Task t2 receives the message from the queue and simply
 * displays the message.
 */
 
/* includes */
#include "vxWorks.h"
#include "msgQLib.h"
 
/* defines */
#define MAX_MSGS (10)
#define MAX_MSG_LEN (100)
 
MSG_Q_ID myMsgQId;
 
task2 (void)
    {
    char msgBuf[MAX_MSG_LEN];
 
    /* get message from queue; if necessary wait until msg is available */
    if (msgQReceive(myMsgQId, msgBuf, MAX_MSG_LEN, WAIT_FOREVER) == ERROR)
        return (ERROR);
 
    /* display message */
    printf ("Message from task 1:\n%s\n", msgBuf);
    }
 
#define MESSAGE "Greetings from Task 1"
task1 (void)
    {
    /* create message queue */
    if ((myMsgQId = msgQCreate (MAX_MSGS, MAX_MSG_LEN, MSG_Q_PRIORITY)) 
        == NULL)
        return (ERROR);
 
    /* send a normal priority message, blocking if queue is full */
    if (msgQSend (myMsgQId, MESSAGE, sizeof (MESSAGE), WAIT_FOREVER,
                  MSG_PRI_NORMAL) == ERROR)
        return (ERROR);
    }
   
實時系統常常構形成任務的客戶機/服務器使用模式。
vxWorks事件是一種在任務和中斷處理程序間,或任務和vxWorks結構體間的通訊方式。
看門狗定時器函數調用
wdCreate()  分配並初始化一個看門狗定時器
wdDelete()  終止並釋放一個看門狗定時器
wdStart()   啓動一個看門狗定時器
wdCancel()  取消當前的一個技術的看門狗定時器
/* Creates a watchdog timer and sets it to go off in 3 seconds.*/
 
/* includes */
#include "vxWorks.h"
#include "logLib.h"
#include "wdLib.h"
 
/* defines */
#define  SECONDS (3)
 
WDOG_ID myWatchDogId;
task (void)
{
    /* Create watchdog */
    if ((myWatchDogId = wdCreate( )) == NULL)
        return (ERROR);
 
    /* Set timer to go off in SECONDS - printing a message to stdout */
    if (wdStart (myWatchDogId, sysClkRateGet( ) * SECONDS, logMsg, 
                 "Watchdog timer just expired\n") == ERROR)
        return (ERROR);
    /* ... */
}
*******************************************
3、中斷
*******************************************
中斷處理函數
intConnect()  設置中斷處理的C程序
intContext()  若是是從中斷級調用,返回真
intCount()    得到當前中斷嵌套深度
intLevelSet(() 設置處理器的中斷屏蔽級
intLock()     禁止中斷
intUnlock()   從新容許中斷
intVecBaseSet() 設置向量基地址
intVecBaseGet() 獲得向量基地址
intVecSet()   設置異常向量
intVecGet()   得到異常向量
中斷服務程序禁止調用浮點協處理器函數。由於由intConnect()函數創建的中斷驅動代碼不能保存和恢復浮點寄存器。
*******************************************
4、輸入/輸出系統(1)
*******************************************
文件描述符(fd)的默認值:0=標準輸入設備 1=標準輸出設備 2=標準錯誤輸出設備
下例將調用此函數的任務(ID = 表示該任務自己)標準輸出文件(fd =1 )重定向到一個已打開的文件(fd = fileFd).
ioTaskStdSet(0,1,fileFd);
fd = open("name",flags,mode);
文件訪問方式標誌(flags)
O_RDONLY  0(hex)  以只讀方式打開文件
O_WRONLY  1(hex)  以只寫方式打開文件
O_RDWR    2(hex)  以讀寫方式打開文件
O_CREAT   200(hex)創建一個新文件
O_TRUNC   400(hex)刪除該文件

基於多文件描述符的掛起操做:選擇功能The Select Facility
選擇功能中的宏函數
FD_ZERO  將全部標誌位設置爲「0」
FD_SET   對指定文件描述符的標誌位設置爲「1」
FD_CLR   對指定文件描述符的標誌位設置爲"0"
FD_ISSET 若是指定標誌位值爲「1」,則返回「1」;不然返回「0」

/* selServer.c - select example 
 * In this example, a server task uses two pipes: one for normal-priority 
 * requests, the other for high-priority requests. The server opens both 
 * pipes and blocks while waiting for data to be available in at least one 
 * of the pipes. 
 */
 
#include "vxWorks.h"
#include "selectLib.h"
#include "fcntl.h"
 
#define MAX_FDS 2
#define MAX_DATA 1024
#define PIPEHI   "/pipe/highPriority"
#define PIPENORM "/pipe/normalPriority"
 
/************************************************************************
* selServer - reads data as it becomes available from two different pipes 
*
* Opens two pipe fds, reading from whichever becomes available. The 
* server code assumes the pipes have been created from either another 
* task or the shell. To test this code from the shell do the following:
*  -> ld < selServer.o
*  -> pipeDevCreate ("/pipe/highPriority", 5, 1024)
*  -> pipeDevCreate ("/pipe/normalPriority", 5, 1024)
*  -> fdHi = open   ("/pipe/highPriority", 1, 0)
*  -> fdNorm = open ("/pipe/normalPriority", 1, 0)
*  -> iosFdShow
*  -> sp selServer
*  -> i
 
* At this point you should see selServer's state as pended. You can now
* write to either pipe to make the selServer display your message.
*  -> write fdNorm, "Howdy", 6
*  -> write fdHi, "Urgent", 7
*/
 
STATUS selServer (void)
    {
    struct fd_set readFds;      /* bit mask of fds to read from */
    int      fds[MAX_FDS];      /* array of fds on which to pend */
    int      width;             /* number of fds on which to pend */
    int      i;                 /* index for fd array */
    char     buffer[MAX_DATA];  /* buffer for data that is read */

/* open file descriptors */
    if ((fds[0] = open (PIPEHI, O_RDONLY, 0)) == ERROR)
        {
        close (fds[0]);
        return (ERROR);
        }
    if ((fds[1] = open (PIPENORM, O_RDONLY, 0)) == ERROR)
        {
        close (fds[0]);
        close (fds[1]);
        return (ERROR);
        }
/* loop forever reading data and servicing clients */
    FOREVER
        {
        /* clear bits in read bit mask */
        FD_ZERO (&readFds);
 
/* initialize bit mask */
        FD_SET (fds[0], &readFds);
        FD_SET (fds[1], &readFds);
        width = (fds[0] > fds[1]) ? fds[0] : fds[1];
        width++;
 
/* pend, waiting for one or more fds to become ready */
    if (select (width, &readFds, NULL, NULL, NULL) == ERROR)
        {
        close (fds[0]);
        close (fds[1]);
        return (ERROR);
        }
 
/* step through array and read from fds that are ready */
    for (i=0; i< MAX_FDS; i++)
        {
        /* check if this fd has data to read */
        if (FD_ISSET (fds[i], &readFds))
            {
            /* typically read from fd now that it is ready */
            read (fds[i], buffer, MAX_DATA);
            /* normally service request, for this example print it */
            printf ("SELSERVER Reading from %s: %s\n", 
                    (i == 0) ? PIPEHI : PIPENORM, buffer);
            }
        }
    }
    }
*******************************************
4、輸入/輸出系統(2)
*******************************************
異步輸入輸出操做(AIO)
可以在執行普通的內部處理時,同時執行輸入/輸出操做。
異步輸入輸出操做函數
aioPxLibInit()   初始化AIO功能函數庫
aioShow()        顯示AIO功能要求
aio_read()       初始化異步讀操做
aio_write()      初始化異步寫操做
aio_listio()     初始化個數最多爲LIO_MAX的AIO功能請求
aio_error()      在一個AIO操做中尋找錯誤狀態值
aio_return()     在一個已完成的AIO操做中尋找返回狀態值
aio_cancel()     取消一個AIO操做
aio_suspend()    等待一個AIO操做完成、被中斷或超時

vxWorks操做系統中的驅動程序
ttyDrv       終端設備驅動程序
ptyDrv       僞終端設備驅動程序
pipeDrv      管道設備驅動程序
memDrv       僞存儲設備驅動程序
nfsDrv       NFS系統客戶機驅動程序
netDrv       用於遠程文件訪問的網絡驅動程序
ramDrv       用於建立RAM存儲盤的RAM驅動程序
scsiLib      SCSI接口庫

串行I/O設備(終端和僞終端設備)
vxWorks操做系統中的I/O設備是一種緩衝型的串行字節流設備。每一個設備都有一個環形緩衝區用於輸入和輸出操做。
下例是在tty設備上設置除了OPT_MON_TRAP功能外的全部功能;
status = ioctl (fd, FIOSETOPTIONS, OPT_TERMINAL & ~OPT_MON_TRAP);
tty設備的可選項
OPT_LINE      選擇線形傳輸模式
OPT_ECHO      向同一輸出通道迴應輸入的字符
OPT_CRMOD     將輸入的RETURN字符翻譯成NEWLINE標誌;將輸出的NEWLINE標誌翻譯成RETURN-LINEFEED字符
OPT_TANDEM    響應軟件流量控制字符CTRL+Q和CTRL+S(XON and XOFF)
OPT_7_BIT     從全部輸入字節中取出最高位
OPT_MON_TRAP  使特殊ROM軟中斷監控程序字符有效,默認爲CTRL+X
OPT_ABORT     使特殊目標機SHELL程序終止字符,默認爲CTRL+Z
OPT_TERMINAL  將上述選項位設爲「1」
OPT_RAW       不設置上述選項位

tyLib文件支持的I/O操做控制函數
FIOBAUDTATE    對指定參數設置傳輸速率
FIOCANCEL      取消一次讀/寫操做
FIOFLUSH       丟棄輸入和輸出緩衝區中的全部數據
FIOGETNAME     獲取指定文件描述符對應的文件名
FIOGETOPTIONS  返回當前設備選項字內容
FIONREAD       獲取輸入緩衝區中的未讀字節數
FIONWRITE      獲取輸出緩衝區中的字節數
FIOSETOPTIONS  設置設備選項字的內容

管道設備
一個任務能夠向管道寫信息,其餘任務能夠讀取這些信息。
建立管道設備
status = pipeDevCreate("/pipe/name",maxMsgs, maxLength);
pipeDrv文件支持的I/O操做控制函數
FIOFLUSH     丟棄管道中全部信息
FIOGETNAME   獲取指定文件描述符對應的管道名
FIONMSGS     獲取管道中的信息數目
FIONREAD     獲取管道中第一條信息的字節數

僞存儲設備(memDrv)
memDrv驅動程序容許I/O系統訪問存儲器像訪問僞I/O設備同樣。
memDrv文件支持的I/O操做控制函數
FIOSEEK   在文件中設置當前字節偏移量
FIOWHERE  返回當前在文件中的位置

網絡文件系統(NFS)設備
網絡文件系統設備能夠經過NFS協議存取遠程主機上的文件。
下例函數在主機"mars"中安裝名爲「/usr」的系統,本地系統名爲「/vxusr」。
nfsMount("mars","/usr","/vxusr");
nfsDrv文件支持的I/O控制函數
FIOFSTATGET    獲取文件狀態信息
FIOGETNAME     獲取指定文件描述符對應的文件名
FIONREAD       獲取文件中未讀取字節數
FIOREADDIR     讀取下一個目錄入口信息
FIOSEEK        在文件中設置當前字節偏移量
FIOSYNC        向遠程NFS文件刷新數據
FIOWHERE       返回文件中當前字節偏移量

非NFS網絡設備
利用遠程外殼協議(RSH)或文件傳輸協議(FTP)訪問遠程主機上的文件。這些網絡設備須要netDrv驅動程序支持。

I/O系統的功能是將用戶的I/O請求與相應驅動程序中的相應操做函數相連。I/O系統經過維護一個包括每一個驅動程序中每一個操做函數的地址表來完成上述工做。
drvnum = iosDrvInstall(xxCreat,0,xxOpen,0,xxRead,xxWrite,xxIoctl);

塊存取設備
塊存取設備的驅動程序不是與I/O系統直接相連,而是與文件系統相互做用,文件系統再與I/O系統相連.
塊存取設備驅動程序中通用的操做包括:
1初始化硬件2分配並初始化數據結構3創建信號量4初始化中斷向量5容許中斷操做
文件系統將本身做爲驅動程序裝入驅動程序表中,而且經過使用存放於塊存取設備結構BLK_DEV(直接訪問的塊存取設備)或SEQ_DEV(順序訪問的塊存取設備)中的函數地址調用實際的驅動程序。

驅動程序支持庫(對用戶編寫驅動程序有幫助)
errnoLib    錯誤狀態函數庫
ftpLib      ARPA文件傳輸協議函數庫
ioLib       I/O接口函數庫
iosLib      I/O系統函數庫
intLib      中斷支持函數庫
remLib      遠程命令函數庫
rngLib      環形緩衝區子程序函數庫
ttyDrv      終端驅動程序函數庫
wdLib       看門狗定時器函數庫

******************************************* 5、本地文件系統 ******************************************* dosFs文件系統:適用於塊存取設備(磁盤)的實時操做,與MS-DOS文件系統兼容; rawFs文件系統:提供了一種簡單的原始文件系統。該文件系統將整個磁盤看成一個單獨的大文件; tapeFs文件系統: 適用於不使用標準文件或目錄結構的磁帶設備。實際上將磁帶盤看成一個原始設備並將整個磁帶盤看成一個大文件; cdromFs文件系統:容許應用程序從按照ISO9660標準文件系統格式化的CD-ROM設備上讀取數據; TSFS目標服務器文件系統:經過使用Tornado軟件中的目標服務器,使得目標機能夠訪問主機系統的文件。

相關文章
相關標籤/搜索