vxvorks學習2(雙向鏈表和環形緩衝的使用)

雙向鏈表

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 )中做了以下幾步:

  1. RING_ID ringId = (RING_ID) malloc (sizeof (RING)); //爲環形緩衝區分配了數據空間

  2. 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個。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章