使用rawsock,在调试网口的收发时,接收线程需要recvfrom数据,入队;另一个线程出队,供回调函数处理。
由于接收网络报文比较快,为了能够及时接收不丢包,使用了无锁环形队列。基本思想是只要有数据就入队,操作队列尾部;出队操作队列头部,追赶尾部,直到追上为止。
理论上,如果入队很快,出队比较费时,会导致数据覆盖。实际中,可以通过调整队列长度来优化。
在测试过程中,通过调整两个线程的优先级可以解决丢包问题。本人调试环境是dsp的4个core同时通过ethsw发包,会出现出队丢包。后来指定两个线程优先级为99后,不丢包。
后来测试过程通过查看enqueuecnt和dequeuecnt的值,当发包速率为160多mbps时,两者的值不等,而且入队比出队一直大很多,说明有包覆盖现象。
当发包速率为140mbps左右时,两者一直相等,说明没有覆盖。因此可以支持140mbps的速率。
可以根据实际应用情况,通过调节环形buf的个数、线程参数等来优化性能,达到要求。
#define MAXSIZE (1024*10)
#define MAX_BUF_LEN (1024*4)
unsigned int enqueuecnt=0;
unsigned int dequeuecnt=0;
tpyedef struct Tag_Queue
{
unsigned int data[MAXSIZE];
unsigned int len[MAXSIZE];
unsigned int front;
unsigned int back;
unsigned tag;//可用来进行有锁环形队列的标记;
} Queue;
Queue * InitQueue(void)
{
Queue *q;
int i = 0;
q = (Queue *)malloc(sizeof(Queue));
if(NULL == q)
{
return NULL;
}
q->front = 0;
q->back = 0;
memset(q->len, 0, MAXSIZE);
for(i = 0; i< MAXSIZE; i++)
{
q->data[i]=(unsign int *)malloc(MAX_BUF_LEN * sizeof(unsigned int));
if(NULL == q->data[i])
{
return NULL;
}
memset(q->data[i],0, MAX_BUF_LEN*sizeof(unsigned int));
}
return q;
}
int EnQueue(Queue *q, unsigned int * dwaddr, int len)
{
memcpy(q->data[q->back],dwaddr,len);
q->len[q->back]=len;
q->back = (q->back+1)%MAXSIZE;
if(q->back == 0)
{
enqueuecnt++;
}
return 1;
}
int DeQueue(Queue *q, unsigned int * plen)
{
int ret;
if((q->back!= q->front)||(enqueuecnt!=dequeuecnt))
{
ret = q->data[q->front];
*plen=q->len[q->front];
q->front=(q->front+1)%MAXSIZE;
if(q->front == 0)
{
dequeuecnt++;
}
return ret;
}
else
{
timedelay(); //封装nanosleep()
return 0;
}
}