最近看队列集,看到网上说队列集成员句柄里的消息要一次性全拿出来
我理解成是不是往队列集的同一个成员发送多次消息也只会触发一次事件呢?
还是说队列集和队列一样一次发送就触发一次事件?
动手测试一下
代码如下,两个出队列方法:
//test 消息队列集测试
//方法1,是每次只从队列集获取一个消息
printf("\r\n\r\n ********方法1,是每次只从队列集获取一个消息 ********\r\n\r\n" );
Send_data = 1 ;
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
Send_data = 2 ;
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
Send_data = 3 ;
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
Send_data = 4 ;
xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
Send_data = 5 ;
xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
Send_data = 6 ;
xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
while(1)
{
HAL_Delay(100);
ActivatedQueue = xQueueSelectFromSet(T_QueueSet, 0);
if(ActivatedQueue == T_queue1)
{
result = xQueueReceive(T_queue1, &Rev_data, 0);
if( result == pdPASS )
{
printf("\r\n方法1: T_queue1 Receive = %d \r\n", Rev_data );
}
else
{
printf("\r\n方法1: xQueueReceive T_queue1 fail !!! result = %d \r\n", result );
}
}
else if(ActivatedQueue == T_queue2)
{
result = xQueueReceive(T_queue2, &Rev_data, 0);
if( result == pdPASS )
{
printf("\r\n方法1: T_queue2 Receive = %d \r\n", Rev_data );
}
else
{
printf("\r\n方法1: xQueueReceive T_queue2 fail !!! result = %d \r\n", result );
}
}
else { break; }
}
//方法2,是每次从队列集获取到句柄之后,就把该消息队列句柄里的消息全拿出来
printf("\r\n\r\n ********方法2,是每次从队列集获取到句柄之后,就把该消息队列句柄里的消息全拿出来 ********\r\n\r\n" );
Send_data = 11 ;
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
Send_data = 12 ;
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
Send_data = 13 ;
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
Send_data = 14 ;
xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
Send_data = 15 ;
xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
Send_data = 16 ;
xQueueSend(T_queue2, (void *)&Send_data, (TickType_t)2);
while(1)
{
HAL_Delay(100);
ActivatedQueue = xQueueSelectFromSet(T_QueueSet, 0);
if(ActivatedQueue == T_queue1)
{
while( 1 )
{
result = xQueueReceive(T_queue1, &Rev_data, 0);
if( result == pdPASS )
{
printf("\r\n方法2: T_queue1 Receive = %d \r\n", Rev_data );
}
else
{
printf("\r\n方法2: T_queue1 已全部出队列 !!! result = %d \r\n", result );
break;
}
}
}
else if(ActivatedQueue == T_queue2)
{
while( 1 )
{
result = xQueueReceive(T_queue2, &Rev_data, 0);
if( result == pdPASS )
{
printf("\r\n方法2: T_queue2 Receive = %d \r\n", Rev_data );
}
else
{
printf("\r\n方法2: T_queue2 已全部出队列 !!! result = %d \r\n", result );
break;
}
}
}
else { break; }
}
//test 消息队列集测试
最后log结果如下:
********方法1,是每次只从队列集获取一个消息 ********
方法1: T_queue1 Receive = 1
方法1: T_queue1 Receive = 2
方法1: T_queue1 Receive = 3
方法1: T_queue2 Receive = 4
方法1: T_queue2 Receive = 5
方法1: T_queue2 Receive = 6
********方法2,是每次从队列集获取到句柄之后,就把该消息队列句柄里的消息全拿出来 ********
方法2: T_queue1 Receive = 11
方法2: T_queue1 Receive = 12
方法2: T_queue1 Receive = 13
方法2: T_queue1 已全部出队列 !!! result = 0
方法2: T_queue1 已全部出队列 !!! result = 0
方法2: T_queue1 已全部出队列 !!! result = 0
方法2: T_queue2 Receive = 14
方法2: T_queue2 Receive = 15
方法2: T_queue2 Receive = 16
方法2: T_queue2 已全部出队列 !!! result = 0
方法2: T_queue2 已全部出队列 !!! result = 0
方法2: T_queue2 已全部出队列 !!! result = 0
事实证明队列集还是和队列集一样,每send一次就会产生一个事件.
实践出真知
测到这里,我又想到,freertos的消息队列实际是值得拷贝,
那我们往队列集发送一串数组会怎么样呢?
稍加修改上面的代码
static QueueHandle_t T_queue1 = NULL;
static QueueHandle_t T_queue2 = NULL;
static xQueueSetHandle T_QueueSet = NULL;
void Master_EventCreat(void)
{
T_queue1 = xQueueCreate(3, sizeof(char)*100);
if(T_queue1 == NULL){
Error_Handler(__FILE__, __LINE__);
}
T_queue2 = xQueueCreate(3, sizeof(char)*100);
if(T_queue2 == NULL){
Error_Handler(__FILE__, __LINE__);
}
/* 创建多事件等待集合 */
T_QueueSet = xQueueCreateSet( 6 );
if( T_QueueSet == NULL ){
Error_Handler(__FILE__, __LINE__);
}
/* 添加消息队列和信号量到Core_QueueSet, 添加时消息队列和信号量必须是空的 */
xQueueAddToSet(T_queue1, T_QueueSet);
xQueueAddToSet(T_queue2, T_QueueSet);
}
//方法1,是每次只从队列集获取一个消息
printf("\r\n\r\n ********方法1,是每次只从队列集获取一个消息 ********\r\n\r\n" );
snprintf( Send_data, 100, " I AM head1");
snprintf( &Send_data[50], 50, " I AM test1");
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
snprintf( Send_data, 100, " I AM head2");
snprintf( &Send_data[50], 50, " I AM test2");
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
snprintf( Send_data, 100, " I AM head3");
snprintf( &Send_data[50], 50, " I AM test3");
xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);
while(1)
{
HAL_Delay(100);
ActivatedQueue = xQueueSelectFromSet(T_QueueSet, 0);
if(ActivatedQueue == T_queue1)
{
result = xQueueReceive(T_queue1, &Rev_data, 0);
if( result == pdPASS )
{
printf("\r\n方法1: T_queue1 Receive[0] = %s \r\n", Rev_data );
printf("\r\n方法1: T_queue1 Receive[50] = %s \r\n\r\n", &Rev_data[50] );
}
else
{
printf("\r\n方法1: xQueueReceive T_queue1 fail !!! result = %d \r\n", result );
}
}
else { break; }
}
最后log结果如下:
????????所以我想xQueueSend(T_queue1, (void *)&Send_data, (TickType_t)2);是把 Send_data这个变量的的sizeof(char)*100个字节 (因为T_queue1 = xQueueCreate(3, sizeof(char)*100);) 拷贝到自己的消息区了.
? ? ? ? 那么,问题来了,假设我们xQueueSend 和xQueueReceive 的变量小于创建的内存大小,因为他是一直复制xQueueCreate时的大小,那么就会发生访问非法地址!!!
|