You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cbmc/codedetect/examples/freertos/queue_verification_example.c

417 lines
10 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* FreeRTOS队列验证示例
*
* 本示例演示了如何使用CodeDetect系统验证FreeRTOS队列操作的安全性。
* 包括队列创建、发送、接收、溢出处理和并发访问验证。
*/
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
/* 队列配置参数 */
#define QUEUE_LENGTH 10
#define ITEM_SIZE sizeof(uint32_t)
#define MAX_QUEUE_ITEMS 100
/* 任务优先级定义 */
#define PRODUCER_PRIORITY (tskIDLE_PRIORITY + 1)
#define CONSUMER_PRIORITY (tskIDLE_PRIORITY + 2)
#define MONITOR_PRIORITY (tskIDLE_PRIORITY + 3)
/* 队列消息类型 */
typedef struct {
uint32_t message_id;
uint32_t data_value;
TickType_t timestamp;
BaseType_t is_critical;
} QueueMessage_t;
/* 队列统计信息 */
typedef struct {
uint32_t total_sent;
uint32_t total_received;
uint32_t queue_full_errors;
uint32_t queue_empty_errors;
uint32_t checksum_errors;
} QueueStats_t;
/* 全局变量 */
QueueHandle_t xMessageQueue = NULL;
QueueHandle_t xStatsQueue = NULL;
QueueStats_t xQueueStats = {0};
TaskHandle_t xProducerTaskHandle = NULL;
TaskHandle_t xConsumerTaskHandle = NULL;
TaskHandle_t xMonitorTaskHandle = NULL;
/**
* @brief 生产者任务 - 向队列发送消息
*
* 该任务演示了:
* 1. 队列发送操作的错误处理
* 2. 队列满状态的处理
* 3. 消息序列号生成
* 4. 关键消息的优先处理
*
* @param pvParameters 任务参数
*/
void vProducerTask(void *pvParameters) {
QueueMessage_t xMessage;
BaseType_t xSendResult;
uint32_t ulMessageCounter = 0;
/* 参数验证 */
configASSERT(pvParameters != NULL);
configASSERT(xMessageQueue != NULL);
for (;;) {
/* 构建消息 */
xMessage.message_id = ulMessageCounter++;
xMessage.data_value = ulMessageCounter * 2; /* 简单的数据计算 */
xMessage.timestamp = xTaskGetTickCount();
xMessage.is_critical = (ulMessageCounter % 10 == 0); /* 每10个消息一个关键消息 */
/* 尝试发送消息 */
if (xMessage.is_critical) {
/* 关键消息使用更长等待时间 */
xSendResult = xQueueSend(xMessageQueue, &xMessage, pdMS_TO_TICKS(100));
} else {
/* 普通消息使用较短等待时间 */
xSendResult = xQueueSend(xMessageQueue, &xMessage, pdMS_TO_TICKS(10));
}
/* 更新统计信息 */
taskENTER_CRITICAL();
xQueueStats.total_sent++;
if (xSendResult != pdPASS) {
xQueueStats.queue_full_errors++;
}
taskEXIT_CRITICAL();
/* 如果发送失败,记录错误但继续运行 */
if (xSendResult != pdPASS) {
/* 队列满,等待一段时间再试 */
vTaskDelay(pdMS_TO_TICKS(50));
}
/* 控制消息生成速率 */
vTaskDelay(pdMS_TO_TICKS(100));
/* 防止消息计数器溢出 */
if (ulMessageCounter >= MAX_QUEUE_ITEMS) {
ulMessageCounter = 0;
}
}
}
/**
* @brief 消费者任务 - 从队列接收消息
*
* 该任务演示了:
* 1. 队列接收操作的阻塞和非阻塞模式
* 2. 队列空状态的处理
* 3. 消息验证和处理
* 4. 统计信息更新
*
* @param pvParameters 任务参数
*/
void vConsumerTask(void *pvParameters) {
QueueMessage_t xReceivedMessage;
BaseType_t xReceiveResult;
uint32_t ulExpectedId = 0;
/* 参数验证 */
configASSERT(pvParameters != NULL);
configASSERT(xMessageQueue != NULL);
for (;;) {
/* 尝试从队列接收消息 */
xReceiveResult = xQueueReceive(xMessageQueue, &xReceivedMessage, pdMS_TO_TICKS(200));
if (xReceiveResult == pdPASS) {
/* 成功接收消息,进行验证 */
taskENTER_CRITICAL();
xQueueStats.total_received++;
/* 验证消息序列号 */
if (xReceivedMessage.message_id != ulExpectedId) {
xQueueStats.checksum_errors++;
/* 重新同步序列号 */
ulExpectedId = xReceivedMessage.message_id + 1;
} else {
ulExpectedId++;
}
taskEXIT_CRITICAL();
/* 处理消息(这里只是简单验证) */
if (xReceivedMessage.data_value % 2 == 0) {
/* 偶数值处理 */
} else {
/* 奇数值处理 */
}
/* 如果是关键消息,记录到统计队列 */
if (xReceivedMessage.is_critical && xStatsQueue != NULL) {
xQueueSend(xStatsQueue, &xReceivedMessage, 0);
}
} else {
/* 接收超时,记录空队列错误 */
taskENTER_CRITICAL();
xQueueStats.queue_empty_errors++;
taskEXIT_CRITICAL();
}
/* 控制处理速率 */
vTaskDelay(pdMS_TO_TICKS(50));
}
}
/**
* @brief 监控任务 - 监控队列状态和统计信息
*
* @param pvParameters 任务参数
*/
void vMonitorTask(void *pvParameters) {
QueueStats_t local_stats;
UBaseType_t uxItemsWaiting;
QueueMessage_t critical_message;
/* 参数验证 */
configASSERT(pvParameters != NULL);
configASSERT(xMessageQueue != NULL);
for (;;) {
/* 获取队列状态 */
uxItemsWaiting = uxQueueMessagesWaiting(xMessageQueue);
/* 复制统计信息 */
taskENTER_CRITICAL();
local_stats = xQueueStats;
taskEXIT_CRITICAL();
/* 检查队列健康状态 */
if (uxItemsWaiting > QUEUE_LENGTH * 0.8) {
/* 队列接近满,需要关注 */
}
if (local_stats.queue_full_errors > 0 || local_stats.queue_empty_errors > 0) {
/* 有错误发生,可能需要调整 */
}
/* 处理关键消息统计 */
if (xStatsQueue != NULL) {
while (xQueueReceive(xStatsQueue, &critical_message, 0) == pdPASS) {
/* 处理关键消息统计 */
}
}
/* 定期报告 */
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
/**
* @brief 创建队列验证系统
*
* @return BaseType_t 创建结果
*/
BaseType_t xCreateQueueVerificationSystem(void) {
BaseType_t xReturn = pdPASS;
/* 创建主消息队列 */
xMessageQueue = xQueueCreate(QUEUE_LENGTH, ITEM_SIZE);
if (xMessageQueue == NULL) {
return pdFAIL;
}
/* 创建统计信息队列 */
xStatsQueue = xQueueCreate(QUEUE_LENGTH / 2, sizeof(QueueMessage_t));
if (xStatsQueue == NULL) {
vQueueDelete(xMessageQueue);
xMessageQueue = NULL;
return pdFAIL;
}
/* 初始化统计信息 */
memset(&xQueueStats, 0, sizeof(QueueStats_t));
/* 创建生产者任务 */
xReturn = xTaskCreate(
vProducerTask,
"Producer",
configMINIMAL_STACK_SIZE,
NULL,
PRODUCER_PRIORITY,
&xProducerTaskHandle
);
if (xReturn != pdPASS) {
goto cleanup;
}
/* 创建消费者任务 */
xReturn = xTaskCreate(
vConsumerTask,
"Consumer",
configMINIMAL_STACK_SIZE,
NULL,
CONSUMER_PRIORITY,
&xConsumerTaskHandle
);
if (xReturn != pdPASS) {
goto cleanup;
}
/* 创建监控任务 */
xReturn = xTaskCreate(
vMonitorTask,
"Monitor",
configMINIMAL_STACK_SIZE,
NULL,
MONITOR_PRIORITY,
&xMonitorTaskHandle
);
if (xReturn != pdPASS) {
goto cleanup;
}
return pdPASS;
cleanup:
/* 清理已创建的资源 */
if (xProducerTaskHandle != NULL) {
vTaskDelete(xProducerTaskHandle);
xProducerTaskHandle = NULL;
}
if (xConsumerTaskHandle != NULL) {
vTaskDelete(xConsumerTaskHandle);
xConsumerTaskHandle = NULL;
}
if (xMonitorTaskHandle != NULL) {
vTaskDelete(xMonitorTaskHandle);
xMonitorTaskHandle = NULL;
}
vQueueDelete(xStatsQueue);
xStatsQueue = NULL;
vQueueDelete(xMessageQueue);
xMessageQueue = NULL;
return pdFAIL;
}
/**
* @brief 停止队列验证系统
*/
void vStopQueueVerificationSystem(void) {
/* 删除所有任务 */
if (xProducerTaskHandle != NULL) {
vTaskDelete(xProducerTaskHandle);
xProducerTaskHandle = NULL;
}
if (xConsumerTaskHandle != NULL) {
vTaskDelete(xConsumerTaskHandle);
xConsumerTaskHandle = NULL;
}
if (xMonitorTaskHandle != NULL) {
vTaskDelete(xMonitorTaskHandle);
xMonitorTaskHandle = NULL;
}
/* 删除队列 */
if (xStatsQueue != NULL) {
vQueueDelete(xStatsQueue);
xStatsQueue = NULL;
}
if (xMessageQueue != NULL) {
vQueueDelete(xMessageQueue);
xMessageQueue = NULL;
}
}
/**
* @brief 获取队列统计信息
*
* @param pxStats 输出统计信息
* @return BaseType_t 操作结果
*/
BaseType_t xGetQueueStats(QueueStats_t *pxStats) {
if (pxStats == NULL) {
return pdFAIL;
}
taskENTER_CRITICAL();
*pxStats = xQueueStats;
taskEXIT_CRITICAL();
return pdPASS;
}
/**
* @brief 主函数 - 演示队列验证系统
*/
int main(void) {
BaseType_t xResult;
QueueStats_t xStats;
/* 创建队列验证系统 */
xResult = xCreateQueueVerificationSystem();
if (xResult != pdPASS) {
/* 系统创建失败 */
return -1;
}
/* 让系统运行一段时间 */
vTaskDelay(pdMS_TO_TICKS(5000));
/* 获取统计信息 */
xResult = xGetQueueStats(&xStats);
if (xResult == pdPASS) {
/* 可以在这里处理统计信息 */
(void)xStats; /* 避免未使用变量警告 */
}
/* 停止系统 */
vStopQueueVerificationSystem();
return 0;
}
/*
* CodeDetect验证要点
*
* 1. 队列安全验证:
* - 队列创建和删除的正确性
* - 队列满和空状态的处理
* - 队列大小和消息大小的验证
*
* 2. 并发访问验证:
* - 多任务并发访问队列的安全性
* - 关键区域的保护
* - 统计信息的一致性
*
* 3. 内存安全验证:
* - 消息结构的边界检查
* - 队列缓冲区溢出检测
* - NULL指针验证
*
* 4. 错误处理验证:
* - 队列操作失败的处理
* - 资源不足的情况处理
* - 任务同步和通信
*
* 5. CBMC规范生成
* - 队列操作的前置条件
* - 消息完整性约束
* - 并发访问的安全性保证
* - 错误恢复路径
*/