原文:https://blog.csdn.net/u014530704/article/details/79887398
此文主要记录IPC项目中如何运用循环队列来处理多则消息的。
(网络摄像头以下简称IPC)
在项目中,经常会有网络消息处理。现在的安防摄像头很多,通常也会配套一个APP去控制IPC,比如设置移动检测、人脸识别、婴儿哭识别等等。在APP点击一个button,可能会触发APP通过网络发送几则消息给摄像头。
这个时候,IPC需要处理这几则或者十几则消息。如果,IPC处理消息不是并发的,那么就需要不断接收,不断处理。这时候,运用队列的机制,可以让先接收到的消息先处理。
而后接收的消息则等待,典型的先进先出原则。如果IPC处理消息是并发的,同样也可以运用队列的机制,只不过需要在每次访问队列的时候加上锁机制来同步资源。IPC接收到的消息可能会包含APP用户ID、请求的命令、消息的长度等。
那如何处理这些消息呢?大致思路如下:
我们可以把每一则消息带有的信息放到结构体里面。这样,每个结构体就是队列的一个成员。接收消息的线程把消息包装成一个结构体然后在队列(数组)的尾部加上,处理消息的线程取出队列的头部来解析处理,每次解析处理完一则消息,就把消息从队列的头部移除。
所以,我们要定义一个结构体数组,结构体里面还能包含结构体等,只要项目需要,都可以拓展。
程序模板比较简单,关键是知道怎么运用到项目中。
其中需要注意的点是循环队列如何判断空还是满。假设循环队列长度为5,当头指针和尾指针指向同一个地方,我们设为空。当有元素入队,尾指针指向下一个元素,当有元素出队,头指针指向下一个元素。当指向的元素为5时,下一个元素为0。
这样,得出的结论是,当队列为满时,头指针和尾指针是相等的,这和队列为空的时候是一样的。不信,画画图看看。
那怎么处理呢?
往期相关推文:C语言,环形队列
为了区别空队列和满队列,数组多加一个元素,这个元素是不确定的,是可以移动的,它将保证当队列为满时,还空留了一个位置。说起来比较抽象,看以下代码:
bool IsQueueFull()
{
return ((tail + 1) % ARRAR_SIZE == front);
}
上面的函数是判断队列是否为满。这样和队列是否为空的判断方法不一样:
bool IsQueueEmpty(void)
{
return (front == tail);
}
所以,通过在循环数组中加多了一个元素,就能够区分队列是空的还是满的。
大致的模板如下:
#include
#include
//构造不完全填满循环数组,以便区分队列为空还是满。
#define QUEUE_LEN 16
#define ARRAR_SIZE (QUEUE_LEN + 1)
typedef struct student
{
int math;
int English;
char name[32];
} student;
#define QUEUE_TYPE student
typedef enum BOOL_
{
false = 0,
true = 1,
}bool;
//static使全局变量只在本文件中使用
static student studentTable[ARRAR_SIZE];//定义结构体数组
static unsigned int front; //指向队头元素
static unsigned int tail; //指向队尾元素的下一个
bool IsQueueEmpty(void)
{
return (front == tail);
}
bool IsQueueFull()
{
return ((tail + 1) % ARRAR_SIZE == front);
}
bool queueInsert(QUEUE_TYPE value)
{
if(IsQueueFull())
return false;
studentTable[tail] = value;
tail = (tail + 1) % ARRAR_SIZE;
return true;
}
bool queueDelete()
{
if(IsQueueEmpty())
return false;
front = (front + 1) % ARRAR_SIZE;
return true;
}
//测试程序
int main(int argc, char *argv[])
{
student stu;
stu.math = 99;
stu.English = 98;
char name[32]= "xiaoming";
memcpy(stu.name,name,sizeof(name));
queueInsert(stu);
stu.math = 61;
stu.English = 60;
memset(name,0,sizeof(name));
sprintf(name,"xiaohong",sizeof(name));
memcpy(stu.name,name,sizeof(name));
queueInsert(stu);
printf("front = %d,tail = %d,name = %s\n",front,tail,studentTable[front].name);
queueDelete();
printf("front = %d,tail = %d,name = %s\n",front,tail,studentTable[front].name);
return 0;
}
测试结果如下:
由于微信公众号近期改变了推送规则,如果您想经常看到我们的文章,可以在每次阅读后,在页面下方点一个「赞」或「在看」,这样每次推送的文章才会第一时间出现在您的订阅列表里。
版权声明:本文来源网络,免费传达知识,版权归原作者所有。如涉及作品版权问题,请联系我进行删除。
猜你喜欢:
实用 | 10分钟教你搭建一个嵌入式web服务器
干货 | 浅析程序开机自启动
嵌入式周报 | 第 3 期
嵌入式周报 | 第 2 期
嵌入式周报 | 第 1 期
干货 | 嵌入式OTA升级实现原理
几个Makefile通用模板分享!
分享一份嵌入式软件工具清单!
实用 | 一个高性能通信库的简单使用分享
实用工具 | LVGL GUI-Guider的使用分享
C语言、嵌入式中几个非常实用的宏技巧
在公众号聊天界面回复1024,可获取嵌入式资源;回复 m ,可查看文章汇总。
点击阅读原文,查看更多分享。
点个呗