雙向鏈表
1、 數據結構分析
在litLib.h中定義了操作雙向鏈表的基類
typedef struct _Vx_node /* Node of a linked list. */
{
struct _Vx_node *next; /* Points at the next node in the list */
struct _Vx_node *previous; /* Points at the previous node in the list */
} _Vx_NODE;
只有一個指向上一個和指向下一個的指針,數據內容會繼承該類。
typedef struct /* Header for a linked list. */
{
_Vx_NODE node; /* Header list node */
int count; /* Number of nodes in list */
} _Vx_LIST;
LIST是一個指向當前操作的數據頭一個指針,包含一個計數器成員。
以下是操作鏈表的API:
extern void lstLibInit (void);
extern NODE * lstFirst (LIST *pList);
extern NODE * lstGet (LIST *pList);
extern NODE * lstLast (LIST *pList);
extern NODE * lstNStep (NODE *pNode, int nStep);
extern NODE * lstNext (NODE *pNode);
extern NODE * lstNth (LIST *pList, int nodenum);
extern NODE * lstPrevious (NODE *pNode);
extern int lstCount (LIST *pList);
extern int lstFind (LIST *pList, NODE *pNode);
extern void lstAdd (LIST *pList, NODE *pNode);即可
extern void lstConcat (LIST *pDstList, LIST *pAddList);
extern void lstDelete (LIST *pList, NODE *pNode);
extern void lstExtract (LIST *pSrcList, NODE *pStartNode, NODE *pEndNode,
LIST *pDstList);
extern void lstFree (LIST *pList);
extern void lstInit (LIST *pList);
extern void lstInsert (LIST *pList, NODE *pPrev, NODE *pNode);
2、雙向鏈表的使用實例
- 首先需要定義用戶數據,每個用戶數據是一個節點,需要繼承自node類。
struct USER_DATA{
_Vx_NODE LIST;
user_data; //用戶數據
}
- 定義好用戶數據以後,需要對鏈表進行初始化,使用Vxworks爲我們提供的 void lstInit (LIST *pList);該函數需要傳入一個頭節點,直接傳入我們定義的用戶數據即可。
- 接下來接可以使用API進行數據的添加,刪除等操作。下面是具體的實例:
#include<stdio.h>
#include "vxWorks.h"
#include "taskLib.h"
#include "sysLib.h"
#include "stdlib.h"
#include "string.h"
#include "lstLib.h"
typedef struct buf_D{
NODE node;
int buf[2];
}BUF_D;
typedef BUF_D BUF;
LIST *mylist()
{
LIST *buf_drps = (LIST*)malloc(sizeof(LIST*)); //初始化鏈表
lstInit(buf_drps);
BUF *buf=(BUF *)malloc(sizeof(BUF)); //給鏈表添加一個節點
buf->buf[0]=1;
buf->buf[1]=2;
lstAdd(buf_drps,buf);
BUF *buf2=(BUF *)malloc(sizeof(BUF)); //給鏈表添加一個節點
buf2->buf[0]=3;
buf2->buf[1]=4;
lstAdd(buf_drps,buf2);
BUF *buf3=(BUF *)malloc(sizeof(BUF)); //給鏈表添加一個節點
buf3->buf[0]=5;
buf3->buf[1]=6;
lstAdd(buf_drps,buf3);
return buf_drps;
}
#define TASK_PR 90
int taskid;
int buf[10];
void test_task(void) //新任務
{
BUF *buf_drps=mylist();
printf("%d",lstCount(buf_drps));
while(buf_drps->node.next)
printf("%d",((BUF *)lstGet(buf_drps))->buf[1]);
taskDelay(sysClkRateGet()/2);
printf("%d",lstCount(buf_drps));
}
int main()
{
taskid = taskSpawn("tDemo",TASK_PR,VX_NO_STACK_FILL,4000,(FUNCPTR)test_task,0,0,0,0,0,0,0,0,0,0);
taskDelay(sysClkRateGet());
return 0;
}
環形緩衝
數據結構
在rngLib.h中定義了環形緩衝區的數據結構:
typedef struct /* RING - ring buffer */
{
size_t pToBuf; /* offset from start of buffer where to write next */
size_t pFromBuf; /* offset from start of buffer where to read next */
size_t bufSize; /* size of ring in bytes */
char *buf; /* pointer to start of buffer */
} RING;
從以上代碼可以看出,環形緩衝區的使用需要直接定義緩衝區的大小,該緩衝區以字節爲單位進行數據的存儲。通過兩個位置指針來確定當前的數據狀態。
在RING_ID rngCreate ( size_t nbytes )中做了以下幾步:
-
RING_ID ringId = (RING_ID) malloc (sizeof (RING)); //爲環形緩衝區分配了數據空間
-
buffer = (char *) malloc (++nbytes); //爲數據分配空間(注意在buffer被定義成指針,因此需要爲其分配內存空間。這看起來有點像C++拷貝構造的意思)。
ringId->bufSize = nbytes;
ringId->buf = buffer;
rngFlush (ringId); //這個函數是給緩衝區數據清零,我們知道當怕P->read=P->write=0時,是環形緩衝區爲空的條件。也就是把緩衝區清空。
return (ringId); //返回一個操作句柄
VXworks爲我們提供了緩衝區的一些常用的API函數:
extern BOOL rngIsEmpty (RING_ID ringId);
extern BOOL rngIsFull (RING_ID ringId);
extern RING_ID rngCreate (size_t nbytes);
extern size_t rngBufGet (RING_ID rngId, char *buffer, size_t maxbytes);
extern size_t rngBufPut (RING_ID rngId, char *buffer, size_t nbytes);
extern size_t rngFreeBytes (RING_ID ringId);
extern size_t rngNBytes (RING_ID ringId);
extern void rngDelete (RING_ID ringId);
extern void rngFlush (RING_ID ringId);
extern void rngMoveAhead (RING_ID ringId, size_t n);
extern void rngPutAhead (RING_ID ringId, char byte, size_t offset);
有這些函數我們就能夠輕鬆的操作環形緩衝區了。
環形緩衝區操作實例
void ring_test()
{
RING_ID *buf_id;
size_t num=0;
char read_buf[3];
buf_id = rngCreate(64); //分配64字節空間
const char *const str = "hello ring";
rngBufPut(buf_id,str,(strlen(str)+1)); //寫入緩衝區
num = rngNBytes(buf_id);
printf("%d\n",num);
rngBufGet(buf_id,read_buf,2); //讀取兩個字符
read_buf[2]='\0';
printf("%s\n",read_buf);
num = rngNBytes(buf_id);
printf("%d\n",num);
}
可以看到,把11個字符放入緩衝區,”讀走兩個以後“,還剩下9個。