前言
在C语言系统开发中,当你完成一些程序模块后,某天可能会意识到:代码编写不是简单的函数堆砌,也不能没有规则的随意组织源文件,因为会极易造成混乱,导致模块间耦合严重、扩展性差、维护困难。因此就需要学习"框架设计",将程序的组织进行抽象和规划。本文面向具有C语言基础的开发者,详细解释了C语言程序框架与常见设计模式,帮助你基于规范化的组织方式构建维护性更好、可扩展性更强的应用程序。
设计模式(Design Patterns),又称软件设计模式,是针对软件工程中常见问题所总结出的可复用解决方案。它为开发者提供了通用的设计思路,有助于提升软件的开发效率、代码的可读性、系统的可扩展性与可维护性。采用广泛认可的设计模式,能够使程序结构更清晰,便于其他熟悉该模式的开发者理解和协作。C语言的软件设计模式一般分为基本设计模式、中级设计模式、高级设计模式。各模式细分如下:
模式类别与细分
| 模式类别 | 模式细分 |
|---|---|
| 基本设计模式 | 状态机模式、事件处理模式、主从设计模式、生产者消费者模式 |
| 中级设计模式 | QMH(队列消息处理器) |
| 高级设计模式 | 面向对象的设计模式、Actor设计模式 |
C语言作为一种经典的系统编程语言,虽然没有原生支持面向对象语法,但通过结构体、函数指针、回调机制等特性,同样可以实现各种经典设计模式。本文将深入探讨这些模式在C语言中的实现方式,提供完整的代码示例和详细的设计分析。
一、基本设计模式
基本设计模式处理的是至少包含一个事件循环的简单模式,或者是多个执行单元之间仅在一个方向上进行通信的模式。常见的有单循环和多循环架构,其中单循环包含状态机、事件处理结构,多循环包含主从结构、生产者/消费者结构。
1.1 单循环设计模式
1.1.1 状态机模式
1.1.1.1 概述
状态机是C语言中最基本且常用的一种设计模式,它用来实现复杂的决策流程,通常通过状态图或流程图来表示。简单来说,状态机就是程序根据当前"状态"来决定下一步做什么,适合用在那些有不同工作阶段或步骤的场景中。状态机是C语言开发人员经常用来快速构建应用程序的基本架构之一,特别适合用于实现复杂的决策逻辑,这类逻辑通常可以用状态图或流程图来表示。
在嵌入式系统、通信协议、用户界面交互等领域,状态机模式展现出了独特的优势。与面向对象语言不同,C语言实现状态机更加贴近底层,性能更高,资源占用更少。状态机可以完全依靠C语言自带的基本语法结构实现,无需额外依赖任何第三方库,简单高效,易于上手,特别适合资源受限的嵌入式环境。
1.1.1.2 状态机的核心实现机制
在C语言中,状态机一般通过以下三种核心方式实现:
1. 枚举类型+Switch-Case结构(推荐) 这是C语言中最标准、最可读的状态机实现方式。使用enum定义所有可能的状态,然后在主循环中使用switch-case结构根据当前状态执行相应代码。状态的转移通过修改状态变量实现。
c
复制
// 状态枚举定义
typedef enum {
STATE_INIT,
STATE_IDLE,
STATE_PROCESSING,
STATE_ERROR,
STATE_SHUTDOWN
} SystemState;
// 状态机上下文结构
typedef struct {
SystemState current_state;
void* context_data; // 状态相关的上下文数据
} StateMachine;
// 主状态机循环
void state_machine_run(StateMachine* sm) {
while (sm->current_state != STATE_SHUTDOWN) {
switch (sm->current_state) {
case STATE_INIT:
// 初始化操作
if (init_success()) {
sm->current_state = STATE_IDLE;
} else {
sm->current_state = STATE_ERROR;
}
break;
case STATE_IDLE:
// 等待事件或条件
if (has_work()) {
sm->current_state = STATE_PROCESSING;
}
break;
case STATE_PROCESSING:
// 处理数据
process_data();
sm->current_state = STATE_IDLE;
break;
case STATE_ERROR:
// 错误处理
handle_error();
sm->current_state = STATE_SHUTDOWN;
break;
default:
// 未知状态处理
sm->current_state = STATE_ERROR;
break;
}
}
}
2. 函数指针数组(状态表) 对于状态非常多的复杂系统,可以使用函数指针数组实现状态表,将状态与处理函数映射起来,提高执行效率。
c
复制
// 状态处理函数原型
typedef void (*StateHandler)(StateMachine* sm);
// 状态处理函数实现
void handle_init(StateMachine* sm) {
if (init_success()) {
sm->current_state = STATE_IDLE;
} else {
sm->current_state = STATE_ERROR;
}
}
void handle_idle(StateMachine* sm) {
if (has_work()) {
sm->current_state = STATE_PROCESSING;
}
}
void handle_processing(StateMachine* sm) {
process_data();
sm->current_state = STATE_IDLE;
}
void handle_error(StateMachine* sm) {
handle_error();
sm->current_state = STATE_SHUTDOWN;
}
// 状态表定义
static StateHandler state_table[] = {
[STATE_INIT] = handle_init,
[STATE_IDLE] = handle_idle,
[STATE_PROCESSING] = handle_processing,
[STATE_ERROR] = handle_error,
[STATE_SHUTDOWN] = NULL
};
// 状态机执行函数
void state_machine_execute(StateMachine* sm) {
while (sm->current_state != STATE_SHUTDOWN) {
StateHandler handler = state_table[sm->current_state];
if (handler) {
handler(sm);
} else {
// 无效状态处理
sm->current_state = STATE_ERROR;
}
}
}
3. 字符串键值对(哈希表) 对于需要动态添加状态或从配置文件加载状态的场景,可以使用字符串作为状态标识,配合哈希表实现灵活的状态映射。
c
复制
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// 状态处理函数原型
typedef void (*StateHandler)(void* context);
// 状态节点
typedef struct StateNode {
char* state_name;
StateHandler handler;
struct StateNode* next;
} StateNode;
// 简单哈希表实现
#define HASH_TABLE_SIZE 32
typedef struct {
StateNode* buckets[HASH_TABLE_SIZE];
} StateHashTable;
// 哈希函数
unsigned int hash(const char* str) {
unsigned int hash = 5381;
int c;
while ((c = *str++)) {
hash = ((hash << 5) + hash) + c;
}
return hash % HASH_TABLE_SIZE;
}
// 添加状态到哈希表
void state_table_add(StateHashTable* table, const char* state_name, StateHandler handler) {
unsigned int index = hash(state_name);
StateNode* node = (StateNode*)malloc(sizeof(StateNode));
node->state_name = strdup(state_name);
node->handler = handler;
node->next = table->buckets[index];
table->buckets[index] = node;
}
// 查找状态处理函数
StateHandler state_table_find(StateHashTable* table, const char* state_name) {
unsigned int index = hash(state_name);
StateNode* node = table->buckets[index];
while (node) {
if (strcmp(node->state_name, state_name) == 0) {
return node->handler;
}
node = node->next;
}
return NULL;
}
// 示例状态处理函数
void state_init_handler(void* ctx) {
printf("执行初始化状态\n");
// 状态转移逻辑
}
void state_idle_handler(void* ctx) {
printf("执行空闲状态\n");
}
// 使用示例
int main() {
StateHashTable table = {0};
state_table_add(&table, "INIT", state_init_handler);
state_table_add(&table, "IDLE", state_idle_handler);
char current_state[32] = "INIT";
void* context = NULL;
while (strcmp(current_state, "EXIT") != 0) {
StateHandler handler = state_table_find(&table, current_state);
if (handler) {
handler(context);
// 根据业务逻辑更新current_state
strcpy(current_state, "IDLE");
} else {
printf("未知状态: %s\n", current_state);
break;
}
}
return 0;
}
状态表示方式对比:
表格
复制
| 表示方式 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 枚举类型 | 类型安全,编译时检查,执行效率高 | 不够灵活,需要预定义所有状态 | 状态固定,性能要求高的系统 |
| 整数 | 执行效率最高,资源占用少 | 可读性差,易出错,维护困难 | 资源极度受限的嵌入式系统 |
| 字符串 | 灵活,可读性强,支持动态状态 | 内存占用大,执行效率较低 | 需要动态配置,状态数量不确定 |
1.1.1.3 为何使用状态机
状态机适用于具有多个明确状态的应用程序。在这种架构中,每个状态都可以根据条件转移到一个或多个其他状态,或者直接结束整个流程。状态的切换通常由用户输入、传感器数据或当前状态中的计算结果决定。在很多应用中,状态机会从一个"初始化"状态开始,接着进入一个"默认"状态。默认状态中可以根据不同情况执行多种操作,具体行为由前一个状态、当前输入以及内部状态综合决定。此外,状态机中还常包含一个"关闭"状态,用于程序结束前的资源释放和清理操作。
除了强大的决策逻辑实现能力,状态机还体现了程序功能的有序组织结构,是应用程序设计的重要组成部分。随着应用规模的扩大和逻辑的复杂化,对良好结构设计的需求也越来越高。此时,结合状态图或流程图进行规划将非常有帮助,甚至在某些项目中是必不可少的。状态机不仅有助于梳理设计思路,还易于搭建和扩展,非常适合构建结构清晰、逻辑严谨的程序。
状态机的核心优势:
-
可预测性:系统行为完全由当前状态和输入决定,便于调试和测试
-
低耦合:每个状态独立处理自己的逻辑,状态间通过清晰接口通信
-
可扩展性:新增状态只需添加case分支,不影响现有状态
-
资源可控:明确的进入/退出点便于资源管理
-
可视化:可直接映射到UML状态图,便于团队沟通
典型用例分析:
1. 嵌入式设备控制 在工业控制器中,设备通常有明确的运行阶段:启动自检、正常运行、故障处理、关机等。每个阶段对应一个状态,状态机确保设备按预定流程安全运行。
c
复制
// 设备控制器状态机示例
typedef enum {
DEVICE_POWER_ON,
DEVICE_SELF_TEST,
DEVICE_STANDBY,
DEVICE_OPERATING,
DEVICE_FAULT,
DEVICE_SHUTDOWN
} DeviceState;
typedef struct {
DeviceState state;
uint32_t error_code;
uint32_t operation_count;
} DeviceController;
void device_control_loop(DeviceController* ctrl) {
while (1) {
switch (ctrl->state) {
case DEVICE_POWER_ON:
if (power_supply_stable()) {
ctrl->state = DEVICE_SELF_TEST;
}
break;
case DEVICE_SELF_TEST:
if (run_self_test()) {
ctrl->state = DEVICE_STANDBY;
} else {
ctrl->state = DEVICE_FAULT;
ctrl->error_code = SELF_TEST_FAILED;
}
break;
case DEVICE_STANDBY:
if (start_command_received()) {
ctrl->state = DEVICE_OPERATING;
} else if (shutdown_command_received()) {
ctrl->state = DEVICE_SHUTDOWN;
}
break;
case DEVICE_OPERATING:
if (perform_operation()) {
ctrl->operation_count++;
if (ctrl->operation_count >= MAX_OPERATIONS) {
ctrl->state = DEVICE_STANDBY;
}
} else {
ctrl->state = DEVICE_FAULT;
ctrl->error_code = OPERATION_FAILED;
}
break;
case DEVICE_FAULT:
handle_fault(ctrl->error_code);
if (reset_command_received()) {
ctrl->state = DEVICE_SELF_TEST;
} else if (shutdown_command_received()) {
ctrl->state = DEVICE_SHUTDOWN;
}
break;
case DEVICE_SHUTDOWN:
perform_safe_shutdown();
return; // 退出循环
}
}
}
2. 通信协议解析 TCP/IP协议栈、Modbus等工业协议都有明确的状态转换:连接建立、数据接收、报文解析、响应发送、连接关闭等。
c
复制
// Modbus RTU从机状态机
typedef enum {
MODBUS_IDLE,
MODBUS_RECEIVE_ADDRESS,
MODBUS_RECEIVE_FUNCTION,
MODBUS_RECEIVE_DATA,
MODBUS_CALCULATE_CRC,
MODBUS_PROCESS_REQUEST,
MODBUS_SEND_RESPONSE,
MODBUS_ERROR
} ModbusState;
void modbus_slave_handler(ModbusState* state, uint8_t byte) {
static ModbusFrame frame;
switch (*state) {
case MODBUS_IDLE:
if (byte == SLAVE_ADDRESS) {
frame.address = byte;
*state = MODBUS_RECEIVE_FUNCTION;
}
break;
case MODBUS_RECEIVE_FUNCTION:
frame.function = byte;
frame.data_index = 0;
*state = MODBUS_RECEIVE_DATA;
break;
case MODBUS_RECEIVE_DATA:
frame.data[frame.data_index++] = byte;
if (frame.data_index >= get_expected_length(frame.function)) {
*state = MODBUS_CALCULATE_CRC;
}
break;
case MODBUS_CALCULATE_CRC:
frame.crc_low = byte;
*state = MODBUS_PROCESS_REQUEST;
break;
case MODBUS_PROCESS_REQUEST:
if (validate_crc(&frame)) {
process_modbus_request(&frame);
*state = MODBUS_SEND_RESPONSE;
} else {
*state = MODBUS_ERROR;
}
break;
case MODBUS_SEND_RESPONSE:
send_response(&frame);
*state = MODBUS_IDLE;
break;
case MODBUS_ERROR:
send_exception();
*state = MODBUS_IDLE;
break;
}
}
3. 用户界面交互 在基于LCD和按键的嵌入式UI中,不同的菜单项对应不同状态,按键事件触发状态转移。
c
复制
// 菜单导航状态机
typedef enum {
MENU_MAIN,
MENU_SETTINGS,
MENU_DISPLAY_ADJUST,
MENU_NETWORK_CONFIG,
MENU_FACTORY_RESET,
MENU_CONFIRM_RESET
} MenuState;
typedef struct {
MenuState current_menu;
uint8_t selected_item;
void (*display_func)(void);
} MenuSystem;
void menu_event_handler(MenuSystem* menu, KeyEvent key) {
switch (menu->current_menu) {
case MENU_MAIN:
if (key == KEY_DOWN) {
menu->selected_item = (menu->selected_item + 1) % 3;
update_main_menu_highlight(menu->selected_item);
} else if (key == KEY_ENTER) {
switch (menu->selected_item) {
case 0: menu->current_menu = MENU_SETTINGS; break;
case 1: menu->current_menu = MENU_DISPLAY_ADJUST; break;
case 2: menu->current_menu = MENU_NETWORK_CONFIG; break;
}
}
break;
case MENU_SETTINGS:
if (key == KEY_BACK) {
menu->current_menu = MENU_MAIN;
} else if (key == KEY_ENTER && menu->selected_item == 2) {
menu->current_menu = MENU_FACTORY_RESET;
}
break;
case MENU_FACTORY_RESET:
if (key == KEY_ENTER) {
menu->current_menu = MENU_CONFIRM_RESET;
} else if (key == KEY_BACK) {
menu->current_menu = MENU_SETTINGS;
}
break;
case MENU_CONFIRM_RESET:
if (key == KEY_ENTER) {
perform_factory_reset();
menu->current_menu = MENU_MAIN;
} else if (key == KEY_BACK) {
menu->current_menu = MENU_FACTORY_RESET;
}
break;
}
// 更新显示
menu->display_func();
}
状态机设计最佳实践:
-
明确状态边界:每个状态应该有清晰的进入和退出条件
-
避免状态爆炸:当状态过多时考虑使用分层状态机(Hierarchical State Machine)
-
统一错误处理:设计统一的错误状态转移路径
-
状态保护:在状态转移时进行合法性检查,防止非法转移
-
日志记录:记录状态转移历史,便于调试和问题追踪
-
原子性操作:在多线程环境中,状态转移需要加锁保护
c
复制
// 线程安全的状态机实现
typedef struct {
SystemState state;
pthread_mutex_t state_lock;
pthread_cond_t state_changed;
void* context;
} ThreadSafeStateMachine;
void safe_state_transition(ThreadSafeStateMachine* sm, SystemState new_state) {
pthread_mutex_lock(&sm->state_lock);
// 验证状态转移合法性
if (is_valid_transition(sm->state, new_state)) {
sm->state = new_state;
pthread_cond_broadcast(&sm->state_changed);
} else {
log_invalid_transition(sm->state, new_state);
}
pthread_mutex_unlock(&sm->state_lock);
}
SystemState safe_state_get(ThreadSafeStateMachine* sm) {
pthread_mutex_lock(&sm->state_lock);
SystemState current = sm->state;
pthread_mutex_unlock(&sm->state_lock);
return current;
}
1.1.1.4 完整示例:网络连接状态机
下面提供一个完整的网络客户端状态机实现,展示C语言状态机的实际应用。
c
复制
// network_fsm.h
#ifndef NETWORK_FSM_H
#define NETWORK_FSM_H
#include <stdint.h>
#include <stdbool.h>
// 网络连接状态定义
typedef enum {
NET_STATE_DISCONNECTED,
NET_STATE_CONNECTING,
NET_STATE_CONNECTED,
NET_STATE_AUTHENTICATING,
NET_STATE_AUTH_FAILED,
NET_STATE_READY,
NET_STATE_TRANSMITTING,
NET_STATE_RECEIVING,
NET_STATE_ERROR,
NET_STATE_RECONNECTING
} NetState;
// 网络事件定义
typedef enum {
NET_EVENT_CONNECT_REQUEST,
NET_EVENT_CONNECT_SUCCESS,
NET_EVENT_CONNECT_TIMEOUT,
NET_EVENT_AUTH_SUCCESS,
NET_EVENT_AUTH_DENIED,
NET_EVENT_DATA_TO_SEND,
NET_EVENT_DATA_RECEIVED,
NET_EVENT_CONNECTION_LOST,
NET_EVENT_ERROR,
NET_EVENT_DISCONNECT_REQUEST
} NetEvent;
// 网络状态机上下文
typedef struct {
NetState current_state;
uint32_t retry_count;
uint32_t last_error;
void* user_data;
uint64_t timestamp;
} NetworkFSM;
// 状态机接口
void network_fsm_init(NetworkFSM* fsm, void* user_data);
void network_fsm_process_event(NetworkFSM* fsm, NetEvent event, void* event_data);
NetState network_fsm_get_state(NetworkFSM* fsm);
const char* network_fsm_state_to_string(NetState state);
#endif // NETWORK_FSM_H
// network_fsm.c
#include "network_fsm.h"
#include <stdio.h>
#include <string.h>
#include <time.h>
// 状态转移表结构
typedef struct {
NetState current_state;
NetEvent event;
NetState next_state;
void (*action)(NetworkFSM*, void*); // 转移时执行的动作
} StateTransition;
// 动作函数实现
static void action_start_connection(NetworkFSM* fsm, void* data) {
printf("[%s] 开始建立连接...\n", network_fsm_state_to_string(fsm->current_state));
// 实际调用connect()系统调用
}
static void action_handle_auth(NetworkFSM* fsm, void* data) {
printf("[%s] 处理认证...\n", network_fsm_state_to_string(fsm->current_state));
// 发送认证数据
}
static void action_send_data(NetworkFSM* fsm, void* data) {
printf("[%s] 发送数据包...\n", network_fsm_state_to_string(fsm->current_state));
// 执行实际数据发送
}
static void action_handle_error(NetworkFSM* fsm, void* data) {
fsm->last_error = (uint32_t)(uintptr_t)data;
printf("[%s] 错误发生: %lu\n", network_fsm_state_to_string(fsm->current_state), fsm->last_error);
}
static void action_attempt_reconnect(NetworkFSM* fsm, void* data) {
fsm->retry_count++;
printf("[%s] 尝试重连,第 %lu 次...\n", network_fsm_state_to_string(fsm->current_state), fsm->retry_count);
if (fsm->retry_count > 3) {
fsm->current_state = NET_STATE_ERROR;
}
}
// 状态转移表定义
static const StateTransition transition_table[] = {
// 当前状态, 事件, 下一状态, 执行动作
{NET_STATE_DISCONNECTED, NET_EVENT_CONNECT_REQUEST, NET_STATE_CONNECTING, action_start_connection},
{NET_STATE_CONNECTING, NET_EVENT_CONNECT_SUCCESS, NET_STATE_AUTHENTICATING, action_handle_auth},
{NET_STATE_CONNECTING, NET_EVENT_CONNECT_TIMEOUT, NET_STATE_RECONNECTING, action_attempt_reconnect},
{NET_STATE_AUTHENTICATING, NET_EVENT_AUTH_SUCCESS, NET_STATE_READY, NULL},
{NET_STATE_AUTHENTICATING, NET_EVENT_AUTH_DENIED, NET_STATE_AUTH_FAILED, action_handle_error},
{NET_STATE_READY, NET_EVENT_DATA_TO_SEND, NET_STATE_TRANSMITTING, action_send_data},
{NET_STATE_TRANSMITTING, NET_EVENT_DATA_SENT, NET_STATE_READY, NULL},
{NET_STATE_READY, NET_EVENT_CONNECTION_LOST, NET_STATE_RECONNECTING, action_attempt_reconnect},
{NET_STATE_ERROR, NET_EVENT_CONNECT_REQUEST, NET_STATE_CONNECTING, action_start_connection},
// ... 更多状态转移
{NET_STATE_ERROR, NET_EVENT_ERROR, NET_STATE_ERROR, action_handle_error} // 默认错误处理
};
#define TRANSITION_COUNT (sizeof(transition_table) / sizeof(transition_table[0]))
// 状态机实现
void network_fsm_init(NetworkFSM* fsm, void* user_data) {
fsm->current_state = NET_STATE_DISCONNECTED;
fsm->retry_count = 0;
fsm->last_error = 0;
fsm->user_data = user_data;
fsm->timestamp = time(NULL);
}
void network_fsm_process_event(NetworkFSM* fsm, NetEvent event, void* event_data) {
printf("事件 %d 在状态 %s 中被处理\n", event, network_fsm_state_to_string(fsm->current_state));
// 查找匹配的状态转移
for (size_t i = 0; i < TRANSITION_COUNT; i++) {
if (transition_table[i].current_state == fsm->current_state &&
transition_table[i].event == event) {
// 执行转移动作
if (transition_table[i].action) {
transition_table[i].action(fsm, event_data);
}
// 状态转移
NetState old_state = fsm->current_state;
fsm->current_state = transition_table[i].next_state;
fsm->timestamp = time(NULL);
printf("状态转移: %s -> %s\n",
network_fsm_state_to_string(old_state),
network_fsm_state_to_string(fsm->current_state));
return;
}
}
// 未找到有效转移
printf("警告: 状态 %s 无法处理事件 %d\n",
network_fsm_state_to_string(fsm->current_state), event);
}
NetState network_fsm_get_state(NetworkFSM* fsm) {
return fsm->current_state;
}
const char* network_fsm_state_to_string(NetState state) {
static const char* state_names[] = {
"DISCONNECTED", "CONNECTING", "CONNECTED", "AUTHENTICATING",
"AUTH_FAILED", "READY", "TRANSMITTING", "RECEIVING",
"ERROR", "RECONNECTING"
};
return state_names[state];
}
// main.c 测试程序
#include "network_fsm.h"
#include <unistd.h>
int main() {
NetworkFSM fsm;
network_fsm_init(&fsm, NULL);
// 模拟网络连接过程
network_fsm_process_event(&fsm, NET_EVENT_CONNECT_REQUEST, NULL);
sleep(1);
network_fsm_process_event(&fsm, NET_EVENT_CONNECT_SUCCESS, NULL);
sleep(1);
network_fsm_process_event(&fsm, NET_EVENT_AUTH_SUCCESS, NULL);
sleep(1);
network_fsm_process_event(&fsm, NET_EVENT_DATA_TO_SEND, NULL);
sleep(1);
network_fsm_process_event(&fsm, NET_EVENT_CONNECTION_LOST, NULL);
return 0;
}
编译运行:
bash
复制
gcc -o network_fsm network_fsm.c main.c -lpthread
./network_fsm
状态机的高级话题:
分层状态机(Hierarchical State Machine) 当状态数量超过20个时,扁平状态机会变得难以维护。分层状态机通过引入状态层次结构,允许子状态继承父状态的转移规则。
c
复制
// 分层状态机实现
typedef struct HSM_State {
const char* name;
struct HSM_State* parent; // 父状态
void (*entry_action)(void*);
void (*exit_action)(void*);
void (*do_action)(void*); // 状态内持续执行的动作
} HSM_State;
typedef struct {
HSM_State* current_state;
void* context;
} HierarchicalFSM;
// 状态转移时执行exit-entry链
void hsm_transition(HierarchicalFSM* hsm, HSM_State* target_state) {
// 找到最近公共祖先
HSM_State* lca = find_lowest_common_ancestor(hsm->current_state, target_state);
// 退出当前状态到LCA
HSM_State* state = hsm->current_state;
while (state != lca) {
if (state->exit_action) state->exit_action(hsm->context);
state = state->parent;
}
// 进入目标状态到LCA的子状态链
// ... 实现状态进入逻辑
}
// 事件处理考虑继承
void hsm_process_event(HierarchicalFSM* hsm, Event* event) {
HSM_State* state = hsm->current_state;
// 先尝试当前状态处理
if (state->handle_event && state->handle_event(hsm->context, event)) {
return; // 事件被处理
}
// 尝试父状态链
while (state->parent) {
state = state->parent;
if (state->handle_event && state->handle_event(hsm->context, event)) {
return;
}
}
// 事件未被处理,记录错误或忽略
}
状态机代码生成工具 对于超大规模状态机(超过100个状态),手写代码不现实。可以使用状态机描述语言(如SCXML)配合代码生成器:
c
复制
// SCXML描述示例
/*
<scxml initial="disconnected">
<state id="disconnected">
<transition event="connect" target="connecting"/>
</state>
<state id="connecting">
<transition event="success" target="connected"/>
<transition event="timeout" target="error"/>
</state>
</scxml>
*/
// 生成的C代码结构
typedef enum {
SCXML_STATE_DISCONNECTED,
SCXML_STATE_CONNECTING,
// ... 更多状态
} ScxmlState;
void scxml_run(ScxmlState* state, ScxmlEvent event) {
static const struct {
ScxmlState current;
ScxmlEvent event;
ScxmlState next;
void (*action)(void);
} transitions[] = {
#include "transitions_table.inc" // 生成的转移表
};
// ... 状态机执行逻辑
}
1.1.2 事件处理模式
1.1.2.1 概述
事件处理程序设计模式为处理系统与外部环境之间的交互提供了一种高效而灵活的架构。它可以用来响应各种外部事件,例如用户输入、硬件中断、定时器触发、网络数据到达等。标准的事件处理程序通常由一个主事件循环和事件分发机制组成。事件循环持续监听事件源,当某个事件被触发时,程序会自动调用相应的事件处理函数。
这种设计方式能让程序对外部事件作出快速响应,同时保持结构清晰,特别适合用于I/O密集型或需要异步响应的应用程序。在C语言中,事件处理模式主要通过回调函数、函数指针数组、事件队列等方式实现。
1.1.2.2 事件处理的核心组件
1. 事件结构定义 统一的事件结构是事件处理系统的基础。
c
复制
// 事件类型枚举
typedef enum {
EVENT_TIMER,
EVENT_KEY_PRESS,
EVENT_MOUSE_CLICK,
EVENT_NETWORK_DATA,
EVENT_SYSTEM_SHUTDOWN,
EVENT_USER_DEFINED
} EventType;
// 基础事件结构
typedef struct Event {
EventType type;
uint32_t timestamp;
void* source; // 事件源
void* data; // 事件特定数据
void (*free_data)(void*); // 数据释放函数
} Event;
// 特定事件数据结构
typedef struct {
int key_code;
int modifiers; // 组合键状态
} KeyEventData;
typedef struct {
int x, y;
int button; // 哪个按键
} MouseEventData;
typedef struct {
size_t data_length;
uint8_t buffer[1024];
} NetworkEventData;
2. 事件队列实现 事件队列是连接事件生产者和消费者的桥梁。
c
复制
// 线程安全的事件队列
typedef struct EventQueue {
Event* events;
size_t capacity;
size_t head;
size_t tail;
size_t count;
pthread_mutex_t mutex;
pthread_cond_t not_empty;
pthread_cond_t not_full;
bool shutdown;
} EventQueue;
// 初始化事件队列
int event_queue_init(EventQueue* queue, size_t capacity) {
queue->events = (Event*)malloc(sizeof(Event) * capacity);
if (!queue->events) return -1;
queue->capacity = capacity;
queue->head = 0;
queue->tail = 0;
queue->count = 0;
queue->shutdown = false;
pthread_mutex_init(&queue->mutex, NULL);
pthread_cond_init(&queue->not_empty, NULL);
pthread_cond_init(&queue->not_full, NULL);
return 0;
}
// 发送事件(生产者)
int event_queue_post(EventQueue* queue, const Event* event) {
pthread_mutex_lock(&queue->mutex);
while (queue->count == queue->capacity && !queue->shutdown) {
pthread_cond_wait(&queue->not_full, &queue->mutex);
}
if (queue->shutdown) {
pthread_mutex_unlock(&queue->mutex);
return -1;
}
// 复制事件
memcpy(&queue->events[queue->tail], event, sizeof(Event));
queue->tail = (queue->tail + 1) % queue->capacity;
queue->count++;
pthread_cond_signal(&queue->not_empty);
pthread_mutex_unlock(&queue->mutex);
return 0;
}
// 接收事件(消费者)
int event_queue_get(EventQueue* queue, Event* event, int timeout_ms) {
pthread_mutex_lock(&queue->mutex);
struct timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
while (queue->count == 0 && !queue->shutdown) {
int ret = pthread_cond_timedwait(&queue->not_empty, &queue->mutex, &timeout);
if (ret == ETIMEDOUT) {
pthread_mutex_unlock(&queue->mutex);
return -2; // 超时
}
}
if (queue->shutdown && queue->count == 0) {
pthread_mutex_unlock(&queue->mutex);
return -1;
}
// 取出事件
memcpy(event, &queue->events[queue->head], sizeof(Event));
queue->head = (queue->head + 1) % queue->capacity;
queue->count--;
pthread_cond_signal(&queue->not_full);
pthread_mutex_unlock(&queue->mutex);
return 0;
}
// 销毁事件队列
void event_queue_destroy(EventQueue* queue) {
pthread_mutex_lock(&queue->mutex);
queue->shutdown = true;
pthread_cond_broadcast(&queue->not_empty);
pthread_cond_broadcast(&queue->not_full);
pthread_mutex_unlock(&queue->mutex);
pthread_mutex_destroy(&queue->mutex);
pthread_cond_destroy(&queue->not_empty);
pthread_cond_destroy(&queue->not_full);
// 释放所有事件的数据
for (size_t i = 0; i < queue->count; i++) {
Event* ev = &queue->events[(queue->head + i) % queue->capacity];
if (ev->free_data && ev->data) {
ev->free_data(ev->data);
}
}
free(queue->events);
}
3. 事件分发器 事件分发器负责将事件路由到对应的处理函数。
c
复制
// 事件处理器类型
typedef bool (*EventHandler)(const Event* event, void* user_data);
// 处理器注册项
typedef struct HandlerNode {
EventType type;
EventHandler handler;
void* user_data;
struct HandlerNode* next;
} HandlerNode;
// 事件分发器
typedef struct EventDispatcher {
HandlerNode* handlers[EVENT_USER_DEFINED + 1]; // 哈希桶
pthread_mutex_t handlers_lock;
} EventDispatcher;
// 注册事件处理器
int dispatcher_register_handler(EventDispatcher* disp, EventType type,
EventHandler handler, void* user_data) {
HandlerNode* node = (HandlerNode*)malloc(sizeof(HandlerNode));
if (!node) return -1;
node->type = type;
node->handler = handler;
node->user_data = user_data;
pthread_mutex_lock(&disp->handlers_lock);
node->next = disp->handlers[type];
disp->handlers[type] = node;
pthread_mutex_unlock(&disp->handlers_lock);
return 0;
}
// 分发事件
bool dispatcher_dispatch(EventDispatcher* disp, const Event* event) {
pthread_mutex_lock(&disp->handlers_lock);
HandlerNode* node = disp->handlers[event->type];
bool handled = false;
while (node) {
if (node->handler(event, node->user_data)) {
handled = true;
break; // 事件被处理,不再传递
}
node = node->next;
}
pthread_mutex_unlock(&disp->handlers_lock);
return handled;
}
1.1.2.3 事件处理循环实现
1. 主事件循环 主事件循环是事件驱动程序的核心。
c
复制
typedef struct EventLoop {
EventQueue* event_queue;
EventDispatcher* dispatcher;
volatile bool running;
pthread_t event_thread;
} EventLoop;
// 事件循环线程函数
static void* event_loop_thread(void* arg) {
EventLoop* loop = (EventLoop*)arg;
Event event;
while (loop->running) {
int ret = event_queue_get(loop->event_queue, &event, 100); // 100ms超时
if (ret == 0) {
// 成功获取事件
bool handled = dispatcher_dispatch(loop->dispatcher, &event);
if (!handled) {
printf("警告: 未处理的事件类型 %d\n", event.type);
}
// 释放事件数据
if (event.free_data && event.data) {
event.free_data(event.data);
}
} else if (ret == -2) {
// 超时,可以执行一些后台任务
continue;
} else if (ret == -1) {
// 队列已关闭
break;
}
}
return NULL;
}
// 启动事件循环
int event_loop_start(EventLoop* loop) {
loop->running = true;
return pthread_create(&loop->event_thread, NULL, event_loop_thread, loop);
}
// 停止事件循环
void event_loop_stop(EventLoop* loop) {
loop->running = false;
event_queue_shutdown(loop->event_queue); // 触发退出
pthread_join(loop->event_thread, NULL);
}
2. 具体事件处理器实现
c
复制
// 定时器事件处理器
static bool timer_handler(const Event* event, void* user_data) {
TimerEventData* data = (TimerEventData*)event->data;
printf("定时器到期: %u ms\n", data->interval);
// 执行定时任务
TimerCallback callback = (TimerCallback)user_data;
callback(data->timer_id);
return true; // 事件已处理
}
// 键盘事件处理器
static bool keyboard_handler(const Event* event, void* user_data) {
KeyEventData* data = (KeyEventData*)event->data;
printf("按键: %d, 组合键: %d\n", data->key_code, data->modifiers);
// 调用按键处理映射
KeyHandler* handlers = (KeyHandler*)user_data;
for (int i = 0; handlers[i].key_code != -1; i++) {
if (handlers[i].key_code == data->key_code) {
handlers[i].callback();
return true;
}
}
return false; // 未处理
}
// 网络事件处理器
static bool network_handler(const Event* event, void* user_data) {
NetworkEventData* data = (NetworkEventData*)event->data;
printf("网络数据到达: %zu 字节\n", data->data_length);
// 处理网络数据
process_network_packet(data->buffer, data->data_length);
return true;
}
3. 完整应用示例:简易GUI系统
c
复制
// gui_system.h
#ifndef GUI_SYSTEM_H
#define GUI_SYSTEM_H
#include "event_system.h"
// GUI组件类型
typedef enum {
GUI_BUTTON,
GUI_LABEL,
GUI_TEXTBOX,
GUI_CHECKBOX
} GUIComponentType;
// GUI组件结构
typedef struct GUIComponent {
int id;
GUIComponentType type;
int x, y, width, height;
char* text;
bool visible;
bool enabled;
void* user_data;
void (*on_click)(struct GUIComponent*, int x, int y);
void (*on_key)(struct GUIComponent*, int key);
struct GUIComponent* parent;
struct GUIComponent** children;
size_t child_count;
} GUIComponent;
// GUI系统初始化
void gui_init(EventLoop* loop);
GUIComponent* gui_create_component(GUIComponentType type, const char* text);
void gui_destroy_component(GUIComponent* comp);
void gui_set_position(GUIComponent* comp, int x, int y);
void gui_set_handler(GUIComponent* comp, EventType type, EventHandler handler);
#endif // GUI_SYSTEM_H
// gui_system.c
#include "gui_system.h"
#include <stdlib.h>
#include <string.h>
static EventLoop* g_event_loop;
static GUIComponent* g_root_window;
void gui_init(EventLoop* loop) {
g_event_loop = loop;
g_root_window = gui_create_component(GUI_LABEL, "root");
}
GUIComponent* gui_create_component(GUIComponentType type, const char* text) {
GUIComponent* comp = (GUIComponent*)calloc(1, sizeof(GUIComponent));
comp->id = rand();
comp->type = type;
comp->text = strdup(text);
comp->visible = true;
comp->enabled = true;
return comp;
}
// 按钮点击事件生成器
void gui_button_clicked(GUIComponent* button, int x, int y) {
Event event = {
.type = EVENT_MOUSE_CLICK,
.timestamp = get_current_time(),
.source = button,
.data = &(MouseEventData){.x = x, .y = y, .button = 1},
.free_data = NULL
};
event_queue_post(g_event_loop->event_queue, &event);
}
// 主程序
int main() {
EventLoop loop;
EventQueue queue;
EventDispatcher dispatcher;
// 初始化事件系统
event_queue_init(&queue, 256);
dispatcher_init(&dispatcher);
loop.event_queue = &queue;
loop.dispatcher = &dispatcher;
// 初始化GUI
gui_init(&loop);
// 创建UI组件
GUIComponent* button = gui_create_component(GUI_BUTTON, "OK");
gui_set_position(button, 100, 100);
// 注册事件处理器
dispatcher_register_handler(&dispatcher, EVENT_MOUSE_CLICK,
button_click_handler, button);
dispatcher_register_handler(&dispatcher, EVENT_TIMER,
screen_update_handler, NULL);
// 启动定时器(模拟)
start_timer(16, TIMER_REPEAT); // 60FPS刷新
// 运行事件循环
event_loop_start(&loop);
// 模拟用户操作
sleep(5);
gui_button_clicked(button, 110, 110);
// 清理
event_loop_stop(&loop);
event_queue_destroy(&queue);
dispatcher_destroy(&dispatcher);
return 0;
}
1.1.2.4 高级事件处理模式
1. 事件优先级处理 在实时系统中,不同事件有不同优先级。
c
复制
// 优先级事件队列
typedef enum {
PRIORITY_HIGH,
PRIORITY_NORMAL,
PRIORITY_LOW
} EventPriority;
typedef struct PriorityEventQueue {
EventQueue* high_queue;
EventQueue* normal_queue;
EventQueue* low_queue;
} PriorityEventQueue;
int priority_queue_get(PriorityEventQueue* pq, Event* event) {
// 高优先级优先
if (event_queue_get(pq->high_queue, event, 0) == 0) return 0;
if (event_queue_get(pq->normal_queue, event, 0) == 0) return 0;
if (event_queue_get(pq->low_queue, event, 0) == 0) return 0;
// 所有队列都为空,阻塞等待
return event_queue_get(pq->normal_queue, event, -1);
}
2. 异步事件处理 使用线程池处理耗时事件,避免阻塞主事件循环。
c
复制
// 线程池事件处理器
typedef struct {
EventHandler sync_handler; // 快速处理
EventHandler async_handler; // 耗时处理
ThreadPool* thread_pool;
} AsyncDispatcher;
void async_dispatch(AsyncDispatcher* ad, const Event* event) {
// 先尝试同步处理
if (ad->sync_handler && ad->sync_handler(event, NULL)) {
return;
}
// 同步无法处理,使用线程池异步执行
thread_pool_submit(ad->thread_pool, ad->async_handler, event);
}
1.2 多循环设计模式
1.2.1 主从设计模式(Master/Slave)
1.2.1.1 概述
主从(Master/Slave)设计模式是C语言开发中常用的多任务架构,适用于需要并行处理多个任务的应用程序。该模式通常由多个并行执行的线程组成,每个线程可以独立以不同的速率执行各自的任务。在这些线程中,其中一个被指定为主线程,负责协调和控制程序的整体流程;其余的则为从线程,负责具体的功能模块或子任务。主线程通过消息传递机制与从线程进行通信,传递方式有消息队列、信号量、共享内存等方式。主线程发送指令或数据,从线程接收后执行对应操作。这样可以实现各模块之间的解耦,使程序结构更清晰,也便于后期扩展与维护。
在C语言中,主从模式通过pthread库实现多线程,配合同步机制确保线程安全。主线程通常负责资源管理、任务调度、异常处理,而从线程专注于具体的计算、I/O操作或数据处理。
1.2.1.2 核心实现机制
1. 基础主从架构
c
复制
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
#include <string.h>
// 任务类型定义
typedef enum {
TASK_COMPUTE,
TASK_IO,
TASK_DATA_PROCESSING,
TASK_PERIODIC
} TaskType;
// 从线程工作单元
typedef struct SlaveWorker {
pthread_t thread;
TaskType type;
bool running;
void* (*task_func)(void*); // 任务函数
void* task_data; // 任务数据
pthread_mutex_t data_lock;
// 与主线程通信
EventQueue* command_queue; // 接收命令
EventQueue* result_queue; // 发送结果
struct SlaveWorker* next;
} SlaveWorker;
// 主线程控制器
typedef struct MasterController {
SlaveWorker* slaves;
size_t slave_count;
bool system_running;
// 全局资源管理
pthread_mutex_t resource_lock;
void* shared_resource;
// 监控线程
pthread_t monitor_thread;
} MasterController;
// 从线程主循环
static void* slave_thread_main(void* arg) {
SlaveWorker* worker = (SlaveWorker*)arg;
printf("从线程 %lu 启动 (类型: %d)\n", pthread_self(), worker->type);
while (worker->running) {
Event command;
// 等待主线程命令(超时100ms)
if (event_queue_get(worker->command_queue, &command, 100) == 0) {
// 处理命令
switch (command.type) {
case EVENT_TASK_START:
printf("从线程 %lu 收到任务开始命令\n", pthread_self());
break;
case EVENT_TASK_STOP:
printf("从线程 %lu 收到停止命令\n", pthread_self());
worker->running = false;
break;
case EVENT_TASK_CONFIG:
printf("从线程 %lu 收到配置更新\n", pthread_self());
pthread_mutex_lock(&worker->data_lock);
// 更新配置
pthread_mutex_unlock(&worker->data_lock);
break;
}
}
// 执行周期性任务
if (worker->task_func) {
void* result = worker->task_func(worker->task_data);
// 发送结果给主线程
if (result) {
Event result_event = {
.type = EVENT_TASK_RESULT,
.source = worker,
.data = result,
.free_data = free // 结果内存由接收方释放
};
event_queue_post(worker->result_queue, &result_event);
}
}
// 根据任务类型调整执行频率
switch (worker->type) {
case TASK_COMPUTE:
usleep(10000); // 10ms
break;
case TASK_IO:
usleep(50000); // 50ms
break;
case TASK_DATA_PROCESSING:
usleep(5000); // 5ms
break;
case TASK_PERIODIC:
usleep(100000); // 100ms
break;
}
}
printf("从线程 %lu 退出\n", pthread_self());
return NULL;
}
// 主线程监控函数
static void* master_monitor(void* arg) {
MasterController* master = (MasterController*)arg;
while (master->system_running) {
// 收集各从线程状态
SlaveWorker* worker = master->slaves;
while (worker) {
pthread_mutex_lock(&worker->data_lock);
printf("监控: 从线程 %lu 运行状态: %s\n",
worker->thread, worker->running ? "正常" : "停止");
pthread_mutex_unlock(&worker->data_lock);
worker = worker->next;
}
sleep(5); // 每5秒检查一次
}
return NULL;
}
// 初始化主从系统
MasterController* master_slave_init(void) {
MasterController* master = (MasterController*)calloc(1, sizeof(MasterController));
if (!master) return NULL;
master->system_running = true;
pthread_mutex_init(&master->resource_lock, NULL);
// 创建监控线程
pthread_create(&master->monitor_thread, NULL, master_monitor, master);
return master;
}
// 添加从线程
SlaveWorker* master_add_slave(MasterController* master, TaskType type,
void* (*task_func)(void*), void* task_data) {
SlaveWorker* worker = (SlaveWorker*)calloc(1, sizeof(SlaveWorker));
if (!worker) return NULL;
worker->type = type;
worker->running = true;
worker->task_func = task_func;
worker->task_data = task_data;
worker->command_queue = event_queue_create(32);
worker->result_queue = event_queue_create(32);
pthread_mutex_init(&worker->data_lock, NULL);
// 创建线程
pthread_create(&worker->thread, NULL, slave_thread_main, worker);
// 加入链表
worker->next = master->slaves;
master->slaves = worker;
master->slave_count++;
return worker;
}
// 主线程命令发送
void master_send_command(MasterController* master, SlaveWorker* worker,
EventType cmd_type, void* cmd_data) {
Event cmd = {
.type = cmd_type,
.source = master,
.data = cmd_data,
.free_data = NULL
};
event_queue_post(worker->command_queue, &cmd);
}
// 资源分配(主线程统一管理)
void* master_allocate_resource(MasterController* master, size_t size) {
pthread_mutex_lock(&master->resource_lock);
master->shared_resource = malloc(size);
pthread_mutex_unlock(&master->resource_lock);
return master->shared_resource;
}
2. 同步机制设计
主从模式的核心是线程间同步,C语言提供了多种同步原语:
c
复制
// 1. 互斥锁保护共享数据
typedef struct SharedData {
pthread_mutex_t lock;
int value;
char buffer[1024];
} SharedData;
void shared_data_update(SharedData* data, int new_value) {
pthread_mutex_lock(&data->lock);
data->value = new_value;
pthread_mutex_unlock(&data->lock);
}
// 2. 条件变量实现等待/通知
typedef struct {
pthread_mutex_t lock;
pthread_cond_t cond;
bool condition_met;
} SignalSync;
void wait_for_signal(SignalSync* sync) {
pthread_mutex_lock(&sync->lock);
while (!sync->condition_met) {
pthread_cond_wait(&sync->cond, &sync->lock);
}
pthread_mutex_unlock(&sync->lock);
}
void send_signal(SignalSync* sync) {
pthread_mutex_lock(&sync->lock);
sync->condition_met = true;
pthread_cond_broadcast(&sync->cond);
pthread_mutex_unlock(&sync->lock);
}
// 3. 读写锁优化读多写少场景
typedef struct {
pthread_rwlock_t rwlock;
ConfigData config;
} SharedConfig;
void config_read(SharedConfig* cfg, ConfigData* out) {
pthread_rwlock_rdlock(&cfg->rwlock);
memcpy(out, &cfg->config, sizeof(ConfigData));
pthread_rwlock_unlock(&cfg->rwlock);
}
void config_update(SharedConfig* cfg, const ConfigData* new_cfg) {
pthread_rwlock_wrlock(&cfg->rwlock);
memcpy(&cfg->config, new_cfg, sizeof(ConfigData));
pthread_rwlock_unlock(&cfg->rwlock);
}
// 4. 信号量控制资源访问
typedef struct {
sem_t semaphore;
int resource_count;
} ResourcePool;
ResourcePool* resource_pool_create(int count) {
ResourcePool* pool = (ResourcePool*)malloc(sizeof(ResourcePool));
pool->resource_count = count;
sem_init(&pool->semaphore, 0, count);
return pool;
}
bool resource_acquire(ResourcePool* pool, int timeout_ms) {
struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);
ts.tv_sec += timeout_ms / 1000;
ts.tv_nsec += (timeout_ms % 1000) * 1000000;
return sem_timedwait(&pool->semaphore, &ts) == 0;
}
void resource_release(ResourcePool* pool) {
sem_post(&pool->semaphore);
}
3. 实际应用案例:多传感器数据采集系统
c
复制
// sensor_system.c
#include "master_slave.h"
#include <stdio.h>
#include <time.h>
// 传感器数据结构
typedef struct {
uint32_t sensor_id;
double temperature;
double humidity;
uint32_t pressure;
uint64_t timestamp;
} SensorData;
// 计算任务:数据滤波
void* compute_task(void* arg) {
static SensorData filtered_data[100];
static int data_index = 0;
// 从共享内存获取原始数据
SensorData* raw = (SensorData*)arg;
// 移动平均滤波
filtered_data[data_index] = *raw;
data_index = (data_index + 1) % 100;
// 计算平均值
double temp_sum = 0;
for (int i = 0; i < 100; i++) {
temp_sum += filtered_data[i].temperature;
}
SensorData* result = (SensorData*)malloc(sizeof(SensorData));
result->sensor_id = raw->sensor_id;
result->temperature = temp_sum / 100.0;
result->timestamp = get_timestamp();
return result;
}
// I/O任务:传感器读取
void* io_task(void* arg) {
uint32_t sensor_id = (uint32_t)(uintptr_t)arg;
SensorData* data = (SensorData*)malloc(sizeof(SensorData));
// 模拟传感器读取
data->sensor_id = sensor_id;
data->temperature = 25.0 + (rand() % 100) / 10.0;
data->humidity = 60 + (rand() % 40);
data->pressure = 101325 + (rand() % 1000);
data->timestamp = get_timestamp();
usleep(100000); // 模拟读取耗时
return data;
}
// 数据处理任务:数据库存储
void* data_processing_task(void* arg) {
SensorData* data = (SensorData*)arg;
char sql[256];
snprintf(sql, sizeof(sql),
"INSERT INTO sensor_data VALUES(%lu, %f, %f, %u, %llu)",
data->sensor_id, data->temperature, data->humidity,
data->pressure, data->timestamp);
// 执行SQL(模拟)
printf("执行SQL: %s\n", sql);
usleep(50000); // 模拟存储耗时
free(data); // 释放数据内存
return NULL;
}
int main() {
MasterController* controller = master_slave_init();
if (!controller) {
fprintf(stderr, "初始化主从系统失败\n");
return 1;
}
// 创建从线程:I/O线程读取三个传感器
for (int i = 0; i < 3; i++) {
SlaveWorker* io_worker = master_add_slave(controller, TASK_IO,
io_task, (void*)(uintptr_t)(1000 + i));
printf("创建传感器读取线程: ID=%d\n", 1000 + i);
}
// 创建从线程:计算线程
SlaveWorker* compute_worker = master_add_slave(controller, TASK_COMPUTE,
compute_task, NULL);
printf("创建数据滤波线程\n");
// 创建从线程:数据存储线程
SlaveWorker* db_worker = master_add_slave(controller, TASK_DATA_PROCESSING,
data_processing_task, NULL);
printf("创建数据库存储线程\n");
// 主线程:命令调度
sleep(2); // 让子线程运行一会儿
// 发送配置命令到计算线程
ConfigData new_config = {.filter_window = 200};
master_send_command(controller, compute_worker, EVENT_TASK_CONFIG, &new_config);
printf("主线程: 系统运行中...\n");
sleep(10);
// 停止系统
printf("主线程: 停止系统\n");
controller->system_running = false;
// 停止所有从线程
SlaveWorker* worker = controller->slaves;
while (worker) {
master_send_command(controller, worker, EVENT_TASK_STOP, NULL);
pthread_join(worker->thread, NULL);
worker = worker->next;
}
pthread_join(controller->monitor_thread, NULL);
free(controller);
return 0;
}
1.2.2 生产者/消费者模式
1.2.2.1 概述
生产者/消费者设计模式是在主从模式基础上发展而来,主要用于优化多个以不同速率运行的执行单元之间的数据共享。它通过将数据生成和数据处理分离,解决了生成速度与消费速度不匹配的问题。在该模式中,程序并行运行两类循环:生产者循环,负责生成数据;消费者循环,负责消费和处理数据。这种结构有效地将生产和消费过程解耦,使得两者可以独立运行,提升系统的稳定性和性能。
在C语言中,生产者/消费者模式通常通过以下方式实现:
-
使用pthread创建生产者线程和消费者线程
-
使用互斥锁保护共享缓冲区
-
使用条件变量实现阻塞等待
-
使用环形缓冲区或队列作为数据缓冲
1.2.2.2 核心实现机制
1. 环形缓冲区(Ring Buffer) 环形缓冲区是生产者/消费者模式的高效实现,避免了频繁的内存分配。
c
复制
// ring_buffer.h
#ifndef RING_BUFFER_H
#define RING_BUFFER_H
#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
// 环形缓冲区结构
typedef struct {
void** buffer; // 数据指针数组
size_t capacity; // 总容量
size_t head; // 写指针
size_t tail; // 读指针
size_t count; // 当前元素数量
// 同步原语
pthread_mutex_t lock;
pthread_cond_t not_full;
pthread_cond_t not_empty;
// 统计信息
uint64_t total_produced;
uint64_t total_consumed;
uint64_t overflow_count;
} RingBuffer;
// 初始化环形缓冲区
RingBuffer* ring_buffer_create(size_t capacity) {
RingBuffer* rb = (RingBuffer*)calloc(1, sizeof(RingBuffer));
if (!rb) return NULL;
rb->buffer = (void**)calloc(capacity, sizeof(void*));
if (!rb->buffer) {
free(rb);
return NULL;
}
rb->capacity = capacity;
rb->head = 0;
rb->tail = 0;
rb->count = 0;
rb->total_produced = 0;
rb->total_consumed = 0;
rb->overflow_count = 0;
pthread_mutex_init(&rb->lock, NULL);
pthread_cond_init(&rb->not_full, NULL);
pthread_cond_init(&rb->not_empty, NULL);
return rb;
}
// 生产者:写入数据
bool ring_buffer_produce(RingBuffer* rb, void* data, int timeout_ms) {
pthread_mutex_lock(&rb->lock);
// 等待缓冲区有空间
struct timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
while (rb->count == rb->capacity) {
if (pthread_cond_timedwait(&rb->not_full, &rb->lock, &timeout) != 0) {
pthread_mutex_unlock(&rb->lock);
rb->overflow_count++;
return false; // 超时或错误
}
}
// 写入数据
rb->buffer[rb->head] = data;
rb->head = (rb->head + 1) % rb->capacity;
rb->count++;
rb->total_produced++;
pthread_cond_signal(&rb->not_empty);
pthread_mutex_unlock(&rb->lock);
return true;
}
// 消费者:读取数据
void* ring_buffer_consume(RingBuffer* rb, int timeout_ms) {
pthread_mutex_lock(&rb->lock);
// 等待数据可用
struct timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
while (rb->count == 0) {
if (pthread_cond_timedwait(&rb->not_empty, &rb->lock, &timeout) != 0) {
pthread_mutex_unlock(&rb->lock);
return NULL; // 超时
}
}
// 读取数据
void* data = rb->buffer[rb->tail];
rb->tail = (rb->tail + 1) % rb->capacity;
rb->count--;
rb->total_consumed++;
pthread_cond_signal(&rb->not_full);
pthread_mutex_unlock(&rb->lock);
return data;
}
// 销毁缓冲区
void ring_buffer_destroy(RingBuffer* rb) {
pthread_mutex_lock(&rb->lock);
// 释放剩余数据
while (rb->count > 0) {
void* data = ring_buffer_consume(rb, 0);
if (data) free(data);
}
pthread_mutex_unlock(&rb->lock);
pthread_mutex_destroy(&rb->lock);
pthread_cond_destroy(&rb->not_full);
pthread_cond_destroy(&rb->not_empty);
free(rb->buffer);
free(rb);
}
#endif // RING_BUFFER_H
2. 多生产者多消费者实现
c
复制
// multi_pc.h
#ifndef MULTI_PC_H
#define MULTI_PC_H
#include "ring_buffer.h"
// 生产者线程结构
typedef struct Producer {
pthread_t thread;
int producer_id;
RingBuffer* output_buffer; // 输出到哪个缓冲区
void* (*produce_func)(void*); // 生产函数
void* user_data;
volatile bool running;
uint64_t items_produced;
} Producer;
// 消费者线程结构
typedef struct Consumer {
pthread_t thread;
int consumer_id;
RingBuffer* input_buffer; // 从哪个缓冲区消费
void (*consume_func)(void*, void*); // 消费函数
void* user_data;
volatile bool running;
uint64_t items_consumed;
} Consumer;
// 生产-消费系统
typedef struct ProducerConsumerSystem {
Producer* producers;
Consumer* consumers;
size_t producer_count;
size_t consumer_count;
RingBuffer** buffers; // 多级缓冲区
size_t buffer_count;
pthread_barrier_t start_barrier; // 同步启动
} ProducerConsumerSystem;
// 创建生产者
Producer* producer_create(int id, RingBuffer* buffer,
void* (*produce)(void*), void* user_data) {
Producer* p = (Producer*)calloc(1, sizeof(Producer));
p->producer_id = id;
p->output_buffer = buffer;
p->produce_func = produce;
p->user_data = user_data;
p->running = true;
return p;
}
// 生产者线程主函数
static void* producer_thread(void* arg) {
Producer* p = (Producer*)arg;
// 等待所有线程就绪
pthread_barrier_wait(&g_system.start_barrier);
printf("生产者 %d 启动\n", p->producer_id);
while (p->running) {
// 生产数据
void* data = p->produce_func(p->user_data);
if (data) {
// 尝试写入(超时1秒)
if (!ring_buffer_produce(p->output_buffer, data, 1000)) {
printf("生产者 %d: 缓冲区满,丢弃数据\n", p->producer_id);
free(data); // 丢弃
} else {
p->items_produced++;
}
}
// 生产频率控制
usleep(10000); // 10ms
}
printf("生产者 %d 退出,共生产 %lu 项\n", p->producer_id, p->items_produced);
return NULL;
}
// 创建消费者
Consumer* consumer_create(int id, RingBuffer* buffer,
void (*consume)(void*, void*), void* user_data) {
Consumer* c = (Consumer*)calloc(1, sizeof(Consumer));
c->consumer_id = id;
c->input_buffer = buffer;
c->consume_func = consume;
c->user_data = user_data;
c->running = true;
return c;
}
// 消费者线程主函数
static void* consumer_thread(void* arg) {
Consumer* c = (Consumer*)arg;
pthread_barrier_wait(&g_system.start_barrier);
printf("消费者 %d 启动\n", c->consumer_id);
while (c->running) {
// 消费数据(超时1秒)
void* data = ring_buffer_consume(c->input_buffer, 1000);
if (data) {
c->consume_func(data, c->user_data);
c->items_consumed++;
free(data); // 消费后释放
} else {
// 超时,可执行空闲任务
// printf("消费者 %d: 等待数据超时\n", c->consumer_id);
}
}
printf("消费者 %d 退出,共消费 %lu 项\n", c->consumer_id, c->items_consumed);
return NULL;
}
// 启动系统
void pc_system_start(ProducerConsumerSystem* system) {
// 启动生产者线程
for (size_t i = 0; i < system->producer_count; i++) {
pthread_create(&system->producers[i].thread, NULL,
producer_thread, &system->producers[i]);
}
// 启动消费者线程
for (size_t i = 0; i < system->consumer_count; i++) {
pthread_create(&system->consumers[i].thread, NULL,
consumer_thread, &system->consumers[i]);
}
// 同步所有线程启动
pthread_barrier_wait(&system->start_barrier);
}
#endif // MULTI_PC_H
3. 有界缓冲区生产消费示例
c
复制
// 实际应用:日志系统
#include "multi_pc.h"
#include <stdarg.h>
// 日志条目
typedef struct LogEntry {
time_t timestamp;
int level;
char message[256];
} LogEntry;
// 生产者:日志写入接口
void log_producer(int level, const char* fmt, ...) {
LogEntry* entry = (LogEntry*)malloc(sizeof(LogEntry));
entry->timestamp = time(NULL);
entry->level = level;
va_list args;
va_start(args, fmt);
vsnprintf(entry->message, sizeof(entry->message), fmt, args);
va_end(args);
// 异步写入缓冲区
ring_buffer_produce(g_log_buffer, entry, 100); // 超时100ms
}
// 消费者:日志写入文件
void log_consumer(void* data, void* user_data) {
LogEntry* entry = (LogEntry*)data;
FILE* fp = (FILE*)user_data;
char time_str[32];
strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", localtime(&entry->timestamp));
const char* level_str[] = {"DEBUG", "INFO", "WARN", "ERROR"};
fprintf(fp, "[%s] [%s] %s\n", time_str, level_str[entry->level], entry->message);
fflush(fp); // 确保写入磁盘
}
// 初始化日志系统
void log_system_init(const char* log_file) {
FILE* fp = fopen(log_file, "a");
if (!fp) {
perror("无法打开日志文件");
return;
}
// 创建缓冲区
g_log_buffer = ring_buffer_create(1024); // 1024条日志缓冲
// 创建消费者线程
Consumer* logger = consumer_create(1, g_log_buffer, log_consumer, fp);
pthread_create(&logger->thread, NULL, consumer_thread, logger);
}
// 使用示例
int main() {
log_system_init("app.log");
// 生产日志
log_producer(LOG_INFO, "系统启动");
for (int i = 0; i < 1000; i++) {
log_producer(LOG_DEBUG, "处理任务 %d", i);
// 模拟工作
usleep(1000);
}
log_producer(LOG_INFO, "系统关闭");
// 等待消费者处理完成
sleep(1);
return 0;
}
1.2.2.3 为何使用生产者/消费者
生产者/消费者模式能够轻松支持多个进程同时运行,并允许它们以不同速率独立迭代。这个模式的核心优势在于它提供了进程间的缓冲通信机制,确保数据在生产和消费之间顺畅传递。当多个进程运行速度不同时,缓冲通信可以有效防止数据丢失或处理瓶颈,保证系统的稳定性和高效运行。
核心优势分析:
-
解耦生产与消费 生产者和消费者不需要知道对方的存在,只依赖共享缓冲区,降低模块耦合度。
-
流量控制 缓冲区天然的背压机制可以防止生产者压垮消费者。
-
并行处理 生产者和消费者可以真正并行执行,充分利用多核CPU。
-
可扩展性 可以增加多个生产者或消费者实例,提高吞吐量。
典型应用场景:
1. 网络数据包处理 网络接收线程(生产者)以线速接收数据包,协议解析线程(消费者)按处理能力消费。
c
复制
// 高性能网络处理器
typedef struct NetworkPacket {
uint8_t* data;
size_t length;
struct timeval timestamp;
} NetworkPacket;
// 生产者:网卡接收线程
void* nic_producer_thread(void* arg) {
RingBuffer* ring = (RingBuffer*)arg;
int sock_fd = create_raw_socket();
while (running) {
NetworkPacket* packet = (NetworkPacket*)malloc(sizeof(NetworkPacket));
packet->data = (uint8_t*)malloc(65536);
packet->length = recv(sock_fd, packet->data, 65536, 0);
gettimeofday(&packet->timestamp, NULL);
// 非阻塞写入
if (!ring_buffer_produce_nonblock(ring, packet)) {
// 缓冲区满,丢弃最差情况
free(packet->data);
free(packet);
drop_count++;
}
}
return NULL;
}
// 消费者:协议解析线程
void* protocol_consumer_thread(void* arg) {
RingBuffer* ring = (RingBuffer*)arg;
while (running) {
NetworkPacket* packet = ring_buffer_consume(ring, -1);
if (packet) {
parse_packet(packet);
// 根据协议类型分发到不同处理线程
switch (get_protocol_type(packet)) {
case PROTOCOL_TCP:
tcp_handler(packet);
break;
case PROTOCOL_UDP:
udp_handler(packet);
break;
}
free(packet->data);
free(packet);
}
}
return NULL;
}
2. 音视频编解码 音频采集(生产者)以固定采样率产生数据,编码线程(消费者)按编码速度处理。
c
复制
// 音频处理流水线
typedef struct AudioFrame {
int16_t samples[1024];
size_t sample_count;
uint32_t timestamp;
} AudioFrame;
// 生产者:音频采集
void* audio_capture_thread (void* arg) {
RingBuffer* rb = (RingBuffer*)arg;
snd_pcm_t* pcm = open_audio_device();
while (recording) {
AudioFrame* frame = (AudioFrame*)malloc(sizeof(AudioFrame));
snd_pcm_readi(pcm, frame->samples, 1024);
frame->timestamp = get_audio_timestamp();
ring_buffer_produce(rb, frame, 50); // 50ms超时
}
return NULL;
}
// 消费者1:实时播放
void* audio_playback_thread(void* arg) {
RingBuffer* rb = (RingBuffer*)arg;
snd_pcm_t* pcm = open_playback_device();
while (playing) {
AudioFrame* frame = ring_buffer_consume(rb, 20);
if (frame) {
snd_pcm_writei(pcm, frame->samples, frame->sample_count);
free(frame);
}
}
return NULL;
}
// 消费者2:编码存储
void* audio_encode_thread(void* arg) {
RingBuffer* rb = (RingBuffer*)arg;
FILE* fp = fopen("audio.dat", "wb");
Encoder* encoder = create_aac_encoder();
while (encoding) {
AudioFrame* frame = ring_buffer_consume(rb, 50);
if (frame) {
uint8_t encoded[2048];
size_t encoded_size = encode(encoder, frame->samples, encoded);
fwrite(encoded, 1, encoded_size, fp);
free(frame);
}
}
fclose(fp);
return NULL;
}
3. 数据库连接池 数据库查询线程(生产者)产生SQL,连接池工作线程(消费者)执行查询。
c
复制
// 数据库请求结构
typedef struct DBRequest {
char sql[1024];
void* result_buffer;
size_t buffer_size;
void (*callback)(void* result, void* user_data);
void* user_data;
} DBRequest;
// 连接池
typedef struct DBConnectionPool {
RingBuffer* request_queue;
RingBuffer* result_queue;
pthread_t* workers;
DBConnection** connections;
size_t connection_count;
} DBConnectionPool;
// 生产者:用户线程
void db_query_async(const char* sql, void (*callback)(void*, void*), void* user_data) {
DBRequest* req = (DBRequest*)malloc(sizeof(DBRequest));
strncpy(req->sql, sql, sizeof(req->sql));
req->callback = callback;
req->user_data = user_data;
// 提交到请求队列
ring_buffer_produce(g_db_pool->request_queue, req, -1);
}
// 消费者:连接池工作线程
void* db_worker_thread(void* arg) {
DBConnection* conn = (DBConnection*)arg;
while (running) {
DBRequest* req = ring_buffer_consume(g_db_pool->request_queue, -1);
if (req) {
// 执行查询
void* result = execute_query(conn, req->sql);
// 如果是同步查询,直接回调
if (req->callback) {
req->callback(result, req->user_data);
free(req);
} else {
// 异步结果,放入结果队列
ring_buffer_produce(g_db_pool->result_queue, result, -1);
}
}
}
return NULL;
}
1.2.2.4 高级生产者/消费者变体
1. 优先级队列 不同优先级的消息需要不同的处理顺序。
c
复制
// 优先级消息结构
typedef struct {
void* data;
int priority; // 优先级数值,越大越优先
uint64_t enqueue_time;
} PriorityItem;
// 优先级缓冲区
typedef struct PriorityBuffer {
PriorityItem* items;
size_t capacity;
size_t count;
pthread_mutex_t lock;
pthread_cond_t not_empty;
} PriorityBuffer;
// 插入时按优先级排序
void priority_buffer_produce(PriorityBuffer* pb, void* data, int priority) {
pthread_mutex_lock(&pb->lock);
// 找到插入位置(按优先级降序)
size_t i = 0;
while (i < pb->count && pb->items[i].priority >= priority) {
i++;
}
// 移动元素腾出空间
if (i < pb->capacity) {
memmove(&pb->items[i+1], &pb->items[i],
(pb->count - i) * sizeof(PriorityItem));
pb->items[i].data = data;
pb->items[i].priority = priority;
pb->items[i].enqueue_time = get_time_ms();
if (pb->count < pb->capacity) pb->count++;
}
pthread_cond_signal(&pb->not_empty);
pthread_mutex_unlock(&pb->lock);
}
// 消费者总是获取最高优先级
void* priority_buffer_consume(PriorityBuffer* pb, int timeout_ms) {
pthread_mutex_lock(&pb->lock);
struct timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += timeout_ms / 1000;
while (pb->count == 0) {
if (pthread_cond_timedwait(&pb->not_empty, &pb->lock, &timeout) != 0) {
pthread_mutex_unlock(&pb->lock);
return NULL;
}
}
void* data = pb->items[0].data;
memmove(&pb->items[0], &pb->items[1],
(pb->count - 1) * sizeof(PriorityItem));
pb->count--;
pthread_mutex_unlock(&pb->lock);
return data;
}
2. 工作窃取(Work Stealing) 多个消费者可以从其他消费者的队列"偷"任务,实现负载均衡。
c
复制
// 工作窃取队列
typedef struct WorkStealingQueue {
Deque* deques; // 每个线程一个双端队列
size_t thread_count;
pthread_mutex_t* locks;
} WorkStealingQueue;
// 消费者消费自己的队列
void* consume_own_queue(WorkStealingQueue* wsq, int thread_id) {
pthread_mutex_lock(&wsq->locks[thread_id]);
void* task = deque_pop_bottom(wsq->deques[thread_id]);
pthread_mutex_unlock(&wsq->locks[thread_id]);
return task;
}
// 窃取其他线程的任务
void* steal_task(WorkStealingQueue* wsq, int thread_id) {
for (int i = 0; i < wsq->thread_count; i++) {
if (i == thread_id) continue;
pthread_mutex_lock(&wsq->locks[i]);
if (!deque_is_empty(wsq->deques[i])) {
void* task = deque_pop_top(wsq->deques[i]);
pthread_mutex_unlock(&wsq->locks[i]);
return task; // 成功窃取
}
pthread_mutex_unlock(&wsq->locks[i]);
}
return NULL;
}
3. 背压机制(Back Pressure) 当消费者跟不上生产者时,需要反馈机制让生产者减速。
c
复制
// 带流量控制的缓冲区
typedef struct BackPressureBuffer {
RingBuffer* buffer;
int high_water_mark; // 高水位
int low_water_mark; // 低水位
bool is_full; // 是否触发背压
void (*on_pressure)(bool high); // 背压回调
} BackPressureBuffer;
bool bp_buffer_produce(BackPressureBuffer* bp, void* data, int timeout) {
bool success = ring_buffer_produce(bp->buffer, data, timeout);
if (success) {
pthread_mutex_lock(&bp->buffer->lock);
size_t count = bp->buffer->count;
pthread_mutex_unlock(&bp->buffer->lock);
// 触发高背压
if (count > bp->high_water_mark && !bp->is_full) {
bp->is_full = true;
if (bp->on_pressure) bp->on_pressure(true);
}
}
return success;
}
void* bp_buffer_consume(BackPressureBuffer* bp, int timeout) {
void* data = ring_buffer_consume(bp->buffer, timeout);
if (data) {
pthread_mutex_lock(&bp->buffer->lock);
size_t count = bp->buffer->count;
pthread_mutex_unlock(&bp->buffer->lock);
// 解除背压
if (count < bp->low_water_mark && bp->is_full) {
bp->is_full = false;
if (bp->on_pressure) bp->on_pressure(false);
}
}
return data;
}
二、中级设计模式
2.1 QMH(队列消息处理器)
2.1.1 概述
QMH(Queued Message Handler)设计模式是将生产者/消费者架构与事件处理架构结合而成的一种高效程序结构。它将用户界面的事件响应与后台任务处理清晰地分离,提升了程序的可维护性和响应效率。在C语言中,QMH通常通过多线程+消息队列的方式实现,主线程处理UI事件并生成消息,工作线程从消息队列取出并处理。
QMH的核心思想是消息驱动,所有操作都封装为消息对象,在不同线程间传递。这种模式特别适合构建响应式的GUI应用、服务器请求处理系统等。
2.1.2 QMH架构详解
1. 消息结构设计 消息是QMH的基本单元,需要包含足够的信息让接收方处理。
c
复制
// message.h
#ifndef MESSAGE_H
#define MESSAGE_H
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
// 消息类型枚举
typedef enum {
// 系统消息
MSG_INIT,
MSG_SHUTDOWN,
MSG_HEARTBEAT,
// 业务消息
MSG_USER_LOGIN,
MSG_USER_LOGOUT,
MSG_DATA_QUERY,
MSG_DATA_UPDATE,
MSG_FILE_UPLOAD,
MSG_FILE_DOWNLOAD,
MSG_CONFIG_CHANGE,
// UI消息
MSG_BUTTON_CLICKED,
MSG_WINDOW_CLOSE,
MSG_MENU_SELECTED,
// 响应消息
MSG_SUCCESS,
MSG_ERROR,
MSG_TIMEOUT,
// 自定义消息起点
MSG_USER_DEFINED = 1000
} MessageType;
// 消息优先级
typedef enum {
MSG_PRIO_HIGH,
MSG_PRIO_NORMAL,
MSG_PRIO_LOW
} MessagePriority;
// 基础消息结构
typedef struct Message {
MessageType type;
MessagePriority priority;
uint32_t source_id; // 消息源ID
uint32_t target_id; // 目标ID(用于多处理器)
uint64_t timestamp;
uint32_t seq_number; // 序列号
void* data; // 消息负载
size_t data_size;
void (*free_data)(void*); // 数据释放函数
struct Message* next; // 链表指针(用于队列)
} Message;
// 消息工厂函数
Message* message_create(MessageType type, void* data, size_t size) {
Message* msg = (Message*)calloc(1, sizeof(Message));
msg->type = type;
msg->priority = MSG_PRIO_NORMAL;
msg->timestamp = get_current_timestamp();
msg->seq_number = atomic_increment(&g_seq_counter);
if (data && size > 0) {
msg->data = malloc(size);
memcpy(msg->data, data, size);
msg->data_size = size;
msg->free_data = free;
}
return msg;
}
// 复制消息
Message* message_clone(const Message* src) {
Message* clone = message_create(src->type, src->data, src->data_size);
clone->priority = src->priority;
clone->source_id = src->source_id;
clone->target_id = src->target_id;
return clone;
}
// 销毁消息
void message_destroy(Message* msg) {
if (msg->free_data && msg->data) {
msg->free_data(msg->data);
}
free(msg);
}
#endif // MESSAGE_H
2. 消息队列实现 支持优先级的线程安全消息队列是QMH的核心。
c
复制
// message_queue.h
#ifndef MESSAGE_QUEUE_H
#define MESSAGE_QUEUE_H
#include "message.h"
#include <pthread.h>
// 消息队列配置
typedef struct MessageQueueConfig {
size_t max_size; // 最大消息数
size_t high_water_mark; // 高水位
size_t low_water_mark; // 低水位
bool enable_priority; // 是否启用优先级
bool blocking; // 是否阻塞
} MessageQueueConfig;
// 消息队列
typedef struct MessageQueue {
Message* head; // 队头
Message* tail; // 队尾
size_t count; // 当前消息数
size_t max_size; // 最大容量
pthread_mutex_t lock;
pthread_cond_t not_empty;
pthread_cond_t not_full;
// 优先级支持
Message* prio_queues[3]; // 三个优先级队列
size_t prio_counts[3];
// 统计
uint64_t total_enqueued;
uint64_t total_dequeued;
uint64_t dropped_messages;
} MessageQueue;
// 初始化队列
MessageQueue* message_queue_create(const MessageQueueConfig* config) {
MessageQueue* queue = (MessageQueue*)calloc(1, sizeof(MessageQueue));
queue->max_size = config->max_size ? config->max_size : 1000;
queue->enable_priority = config->enable_priority;
pthread_mutex_init(&queue->lock, NULL);
pthread_cond_init(&queue->not_empty, NULL);
pthread_cond_init(&queue->not_full, NULL);
return queue;
}
// 入队消息
int message_queue_enqueue(MessageQueue* queue, Message* msg) {
pthread_mutex_lock(&queue->lock);
// 检查容量
if (queue->count >= queue->max_size) {
pthread_mutex_unlock(&queue->lock);
queue->dropped_messages++;
message_destroy(msg);
return -1; // 队列满
}
// 根据优先级放入不同队列
if (queue->enable_priority) {
int prio = msg->priority;
// 添加到优先级队列尾部
if (queue->prio_counts[prio] == 0) {
queue->prio_queues[prio] = msg;
} else {
Message* tail = queue->prio_queues[prio];
while (tail->next) tail = tail->next;
tail->next = msg;
}
queue->prio_counts[prio]++;
} else {
// 普通FIFO队列
if (queue->tail) {
queue->tail->next = msg;
} else {
queue->head = msg;
}
queue->tail = msg;
}
queue->count++;
queue->total_enqueued++;
pthread_cond_signal(&queue->not_empty);
pthread_mutex_unlock(&queue->lock);
return 0;
}
// 出队消息(按优先级)
Message* message_queue_dequeue(MessageQueue* queue, int timeout_ms) {
pthread_mutex_lock(&queue->lock);
// 等待消息可用
struct timespec timeout;
clock_gettime(CLOCK_REALTIME, &timeout);
timeout.tv_sec += timeout_ms / 1000;
timeout.tv_nsec += (timeout_ms % 1000) * 1000000;
while (queue->count == 0) {
if (pthread_cond_timedwait(&queue->not_empty, &queue->lock, &timeout) != 0) {
pthread_mutex_unlock(&queue->lock);
return NULL; // 超时
}
}
// 按优先级选择消息(高->中->低)
Message* msg = NULL;
if (queue->enable_priority) {
for (int prio = MSG_PRIO_HIGH; prio <= MSG_PRIO_LOW; prio++) {
if (queue->prio_counts[prio] > 0) {
msg = queue->prio_queues[prio];
queue->prio_queues[prio] = msg->next;
queue->prio_counts[prio]--;
break;
}
}
} else {
msg = queue->head;
if (queue->head) {
queue->head = queue->head->next;
if (!queue->head) queue->tail = NULL;
}
}
if (msg) {
msg->next = NULL;
queue->count--;
queue->total_dequeued++;
pthread_cond_signal(&queue->not_full);
}
pthread_mutex_unlock(&queue->lock);
return msg;
}
#endif // MESSAGE_QUEUE_H
3. 消息处理器(MH)实现 消息处理器是消费线程,从队列取出消息并执行对应操作。
c
复制
// message_handler.h
#ifndef MESSAGE_HANDLER_H
#define MESSAGE_HANDLER_H
#include "message_queue.h"
// 消息处理函数原型
typedef void (*MessageHandlerFunc)(const Message* msg, void* user_data);
// 处理器映射项
typedef struct HandlerMap {
MessageType type;
MessageHandlerFunc handler;
void* user_data;
struct HandlerMap* next;
} HandlerMap;
// 消息处理器
typedef struct MessageHandler {
const char* name;
uint32_t handler_id;
MessageQueue* input_queue; // 输入消息队列
MessageQueue* output_queue; // 输出队列(用于响应)
HandlerMap* handlers; // 消息处理映射表
pthread_t thread; // 处理线程
pthread_mutex_t handlers_lock;
volatile bool running;
volatile bool busy;
// 统计
uint64_t messages_processed;
uint64_t messages_failed;
uint32_t average_latency_ms; // 平均处理延迟
// 性能控制
size_t max_batch_size; // 批量处理大小
int poll_interval_ms; // 轮询间隔
} MessageHandler;
// 创建消息处理器
MessageHandler* message_handler_create(const char* name, uint32_t id,
MessageQueue* input_q, MessageQueue* output_q) {
MessageHandler* mh = (MessageHandler*)calloc(1, sizeof(MessageHandler));
mh->name = strdup(name);
mh->handler_id = id;
mh->input_queue = input_q;
mh->output_queue = output_q;
mh->running = true;
mh->max_batch_size = 10;
mh->poll_interval_ms = 10;
pthread_mutex_init(&mh->handlers_lock, NULL);
return mh;
}
// 注册消息处理器
int message_handler_register(MessageHandler* mh, MessageType type,
MessageHandlerFunc func, void* user_data) {
HandlerMap* map = (HandlerMap*)malloc(sizeof(HandlerMap));
map->type = type;
map->handler = func;
map->user_data = user_data;
pthread_mutex_lock(&mh->handlers_lock);
map->next = mh->handlers;
mh->handlers = map;
pthread_mutex_unlock(&mh->handlers_lock);
return 0;
}
// 默认消息处理器(未匹配的消息)
static void default_handler(const Message* msg, void* user_data) {
MessageHandler* mh = (MessageHandler*)user_data;
printf("[%s] 未处理的消息类型: %d\n", mh->name, msg->type);
mh->messages_failed++;
}
// 消息处理循环线程
static void* message_handler_thread(void* arg) {
MessageHandler* mh = (MessageHandler*)arg;
printf("消息处理器 '%s' (ID: %u) 启动\n", mh->name, mh->handler_id);
// 注册默认处理器
message_handler_register(mh, MSG_USER_DEFINED, default_handler, mh);
while (mh->running) {
Message* msg = message_queue_dequeue(mh->input_queue, mh->poll_interval_ms);
if (msg) {
uint64_t start_time = get_current_timestamp();
mh->busy = true;
// 查找处理器
pthread_mutex_lock(&mh->handlers_lock);
HandlerMap* map = mh->handlers;
bool handled = false;
while (map) {
if (map->type == msg->type) {
map->handler(msg, map->user_data);
handled = true;
break;
}
map = map->next;
}
pthread_mutex_unlock(&mh->handlers_lock);
if (!handled) {
// 使用默认处理器
default_handler(msg, mh);
}
// 统计
mh->messages_processed++;
uint32_t latency = get_current_timestamp() - start_time;
mh->average_latency_ms = (mh->average_latency_ms + latency) / 2;
// 发送响应消息(如果需要)
if (msg->source_id != 0 && mh->output_queue) {
Message* response = message_create(MSG_SUCCESS, NULL, 0);
response->target_id = msg->source_id;
message_queue_enqueue(mh->output_queue, response);
}
message_destroy(msg);
mh->busy = false;
}
}
printf("消息处理器 '%s' 退出\n", mh->name);
return NULL;
}
// 启动处理器
int message_handler_start(MessageHandler* mh) {
mh->running = true;
return pthread_create(&mh->thread, NULL, message_handler_thread, mh);
}
// 停止处理器
void message_handler_stop(MessageHandler* mh) {
mh->running = false;
// 发送停止消息
Message* stop_msg = message_create(MSG_SHUTDOWN, NULL, 0);
message_queue_enqueue(mh->input_queue, stop_msg);
pthread_join(mh->thread, NULL);
}
#endif // MESSAGE_HANDLER_H
4. QMH协调器 协调器管理所有消息处理器和队列,提供统一接口。
c
复制
// qmh_core.h
#ifndef QMH_CORE_H
#define QMH_CORE_H
#include "message_handler.h"
// QMH系统配置
typedef struct QMHConfig {
size_t handler_count;
size_t queue_size;
bool enable_priority;
size_t max_message_size;
} QMHConfig;
// QMH核心系统
typedef struct QMHCore {
MessageHandler** handlers; // 处理器数组
MessageQueue** queues; // 队列数组
size_t handler_count;
EventLoop* ui_event_loop; // UI事件循环
MessageQueue* ui_queue; // UI消息队列
MessageHandler* master_handler; // 主处理器
volatile bool running;
pthread_t master_thread;
} QMHCore;
// 创建QMH系统
QMHCore* qmh_create(const QMHConfig* config) {
QMHCore* qmh = (QMHCore*)calloc(1, sizeof(QMHCore));
qmh->handler_count = config->handler_count;
// 创建消息队列
MessageQueueConfig qcfg = {
.max_size = config->queue_size,
.enable_priority = config->enable_priority
};
qmh->queues = (MessageQueue**)malloc(sizeof(MessageQueue*) * config->handler_count);
for (size_t i = 0; i < config->handler_count; i++) {
qmh->queues[i] = message_queue_create(&qcfg);
}
// 创建消息处理器
qmh->handlers = (MessageHandler**)malloc(sizeof(MessageHandler*) * config->handler_count);
for (size_t i = 0; i < config->handler_count; i++) {
qmh->handlers[i] = message_handler_create(
get_handler_name(i), i, qmh->queues[i],
i > 0 ? qmh->queues[i-1] : NULL
);
}
// 创建主处理器
qmh->master_handler = message_handler_create("Master", 0xFFFF,
qmh->queues[0], NULL);
return qmh;
}
// 发送消息到指定处理器
int qmh_send_message(QMHCore* qmh, uint32_t handler_id, Message* msg) {
if (handler_id >= qmh->handler_count) {
return -1;
}
msg->target_id = handler_id;
return message_queue_enqueue(qmh->handlers[handler_id]->input_queue, msg);
}
// 广播消息到所有处理器
int qmh_broadcast_message(QMHCore* qmh, Message* msg) {
Message* clones[64];
size_t count = 0;
// 克隆消息
for (size_t i = 0; i < qmh->handler_count && i < 64; i++) {
clones[count++] = message_clone(msg);
}
// 发送到所有队列
for (size_t i = 0; i < count; i++) {
message_queue_enqueue(qmh->queues[i], clones[i]);
}
message_destroy(msg);
return 0;
}
// 启动所有处理器
void qmh_start(QMHCore* qmh) {
qmh->running = true;
// 启动消息处理器线程
for (size_t i = 0; i < qmh->handler_count; i++) {
message_handler_start(qmh->handlers[i]);
}
message_handler_start(qmh->master_handler);
}
// 停止系统
void qmh_shutdown(QMHCore* qmh) {
qmh->running = false;
// 广播停止消息
Message* shutdown_msg = message_create(MSG_SHUTDOWN, NULL, 0);
qmh_broadcast_message(qmh, shutdown_msg);
// 等待所有线程结束
for (size_t i = 0; i < qmh->handler_count; i++) {
message_handler_stop(qmh->handlers[i]);
}
message_handler_stop(qmh->master_handler);
}
#endif // QMH_CORE_H
2.1.3 完整QMH应用示例
下面展示一个基于QMH的实时监控系统实现。
c
复制
// monitor_system.c
#include "qmh_core.h"
#include <stdio.h>
#include <signal.h>
// 全局QMH实例
QMHCore* g_qmh = NULL;
// 信号处理
void signal_handler(int sig) {
printf("\n收到信号 %d,正在关闭系统...\n", sig);
if (g_qmh) {
qmh_shutdown(g_qmh);
}
exit(0);
}
// 数据获取处理器
void data_acquisition_handler(const Message* msg, void* user_data) {
printf("[数据采集] 处理消息类型: %d\n", msg->type);
switch (msg->type) {
case MSG_INIT: {
// 初始化传感器
printf("初始化传感器设备\n");
break;
}
case MSG_DATA_QUERY: {
// 读取传感器数据
int sensor_id = *(int*)msg->data;
float data = read_sensor_data(sensor_id);
// 发送数据更新消息
Message* update_msg = message_create(MSG_DATA_UPDATE, &data, sizeof(float));
update_msg->source_id = 1; // 数据采集处理器ID
qmh_send_message(g_qmh, 2, update_msg); // 发送到数据处理
break;
}
}
}
// 数据处理处理器
void data_processing_handler(const Message* msg, void* user_data) {
printf("[数据处理] 处理消息类型: %d\n", msg->type);
switch (msg->type) {
case MSG_DATA_UPDATE: {
float raw_data = *(float*)msg->data;
// 应用滤波算法
static float filtered_data = 0;
filtered_data = filtered_data * 0.8 + raw_data * 0.2;
// 发送到UI显示
Message* ui_msg = message_create(MSG_DATA_UPDATE, &filtered_data, sizeof(float));
qmh_send_message(g_qmh, 0, ui_msg); // UI处理器ID为0
break;
}
}
}
// UI事件处理器
void ui_event_handler(const Message* msg, void* user_data) {
printf("[UI事件] 处理消息类型: %d\n", msg->type);
switch (msg->type) {
case MSG_BUTTON_CLICKED: {
const char* button_id = (const char*)msg->data;
if (strcmp(button_id, "btn_start") == 0) {
// 发送开始采集命令
Message* start_msg = message_create(MSG_DATA_QUERY, NULL, 0);
qmh_broadcast_message(g_qmh, start_msg);
} else if (strcmp(button_id, "btn_stop") == 0) {
Message* stop_msg = message_create(MSG_SHUTDOWN, NULL, 0);
qmh_broadcast_message(g_qmh, stop_msg);
}
break;
}
case MSG_DATA_UPDATE: {
float data = *(float*)msg->data;
printf("UI更新数据显示: %.2f\n", data);
break;
}
}
}
// 定时器回调(模拟UI事件)
void timer_callback(int timer_id) {
static int click_count = 0;
if (click_count == 0) {
// 模拟点击开始按钮
Message* click_msg = message_create(MSG_BUTTON_CLICKED, "btn_start", 10);
qmh_send_message(g_qmh, 0, click_msg);
} else if (click_count == 100) {
// 模拟点击停止按钮
Message* click_msg = message_create(MSG_BUTTON_CLICKED, "btn_stop", 9);
qmh_send_message(g_qmh, 0, click_msg);
}
click_count++;
}
int main() {
// 设置信号处理
signal(SIGINT, signal_handler);
// 配置QMH系统
QMHConfig config = {
.handler_count = 3,
.queue_size = 100,
.enable_priority = true,
.max_message_size = 1024
};
// 创建QMH系统
g_qmh = qmh_create(&config);
// 注册消息处理器
// 处理器0: UI事件
message_handler_register(g_qmh->handlers[0], MSG_BUTTON_CLICKED,
ui_event_handler, NULL);
message_handler_register(g_qmh->handlers[0], MSG_DATA_UPDATE,
ui_event_handler, NULL);
// 处理器1: 数据采集
message_handler_register(g_qmh->handlers[1], MSG_INIT,
data_acquisition_handler, NULL);
message_handler_register(g_qmh->handlers[1], MSG_DATA_QUERY,
data_acquisition_handler, NULL);
// 处理器2: 数据处理
message_handler_register(g_qmh->handlers[2], MSG_DATA_UPDATE,
data_processing_handler, NULL);
// 启动系统
qmh_start(g_qmh);
// 发送初始化消息
Message* init_msg = message_create(MSG_INIT, NULL, 0);
qmh_broadcast_message(g_qmh, init_msg);
// 启动定时器(每100ms触发一次)
start_timer(100, TIMER_REPEAT, timer_callback);
printf("QMH监控系统运行中,按Ctrl+C退出...\n");
// 主循环(模拟UI线程)
while (g_qmh->running) {
// 处理UI事件(这里简化为定时检查)
usleep(100000); // 100ms
// 实际GUI系统会在这里处理窗口事件
// process_gui_events();
}
// 清理
qmh_shutdown(g_qmh);
free(g_qmh);
return 0;
}
2.1.4 QMH高级特性
1. 消息路由 基于内容的路由可以将消息动态分发到不同处理器。
c
复制
// 路由规则
typedef struct RouteRule {
MessageType type;
uint32_t source_id_pattern;
uint32_t target_id;
bool (*condition)(const Message*); // 条件函数
struct RouteRule* next;
} RouteRule;
// 路由表
typedef struct MessageRouter {
RouteRule* rules;
pthread_rwlock_t rules_lock;
} MessageRouter;
// 路由消息
void route_message(MessageRouter* router, Message* msg, QMHCore* qmh) {
pthread_rwlock_rdlock(&router->rules_lock);
RouteRule* rule = router->rules;
while (rule) {
if (rule->type == msg->type &&
(rule->source_id_pattern == 0 ||
(msg->source_id & rule->source_id_pattern))) {
if (!rule->condition || rule->condition(msg)) {
qmh_send_message(qmh, rule->target_id, message_clone(msg));
}
}
rule = rule->next;
}
pthread_rwlock_unlock(&router->rules_lock);
}
2. 消息持久化 关键消息需要持久化防止系统崩溃丢失。
c
复制
// 持久化消息队列
typedef struct PersistentMessageQueue {
MessageQueue* memory_queue;
FILE* persist_file; // 持久化文件
pthread_mutex_t persist_lock;
uint64_t persist_seq; // 持久化序列号
} PersistentMessageQueue;
// 消息持久化
void persist_message(PersistentMessageQueue* pmq, const Message* msg) {
pthread_mutex_lock(&pmq->persist_lock);
// 写入文件(追加模式)
size_t written = fwrite(&pmq->persist_seq, sizeof(uint64_t), 1, pmq->persist_file);
written += fwrite(&msg->type, sizeof(MessageType), 1, pmq->persist_file);
written += fwrite(&msg->data_size, sizeof(size_t), 1, pmq->persist_file);
if (msg->data_size > 0) {
written += fwrite(msg->data, 1, msg->data_size, pmq->persist_file);
}
fflush(pmq->persist_file);
pmq->persist_seq++;
pthread_mutex_unlock(&pmq->persist_lock);
}
// 恢复持久化消息
void restore_messages(PersistentMessageQueue* pmq) {
fseek(pmq->persist_file, 0, SEEK_SET);
while (!feof(pmq->persist_file)) {
uint64_t seq;
if (fread(&seq, sizeof(uint64_t), 1, pmq->persist_file) != 1) break;
MessageType type;
fread(&type, sizeof(MessageType), 1, pmq->persist_file);
size_t size;
fread(&size, sizeof(size_t), 1, pmq->persist_file);
void* data = NULL;
if (size > 0) {
data = malloc(size);
fread(data, 1, size, pmq->persist_file);
}
Message* msg = message_create(type, data, size);
message_queue_enqueue(pmq->memory_queue, msg);
if (data) free(data);
}
}
三、高级设计模式
3.1 面向对象设计模式
3.1.1 概述
面向对象编程(OOP)是一种常用的编程方式,C语言虽然不是原生面向对象语言,但通过结构体、函数指针、封装等技巧,同样可以实现面向对象的设计模式。LVOOP(LabVIEW面向对象编程)借鉴了其他面向对象语言中的概念,包括类结构、封装和继承。你可以使用这些概念来创建更易维护和修改的代码,而不会影响应用程序中其他部分的代码。
在C语言中实现OOP需要理解以下核心概念:
-
类(Class):用结构体定义,包含数据成员
-
对象(Object):类的实例,即结构体变量
-
方法(Method):操作对象的函数,通常第一个参数是对象指针
-
封装(Encapsulation):通过不透明指针隐藏实现细节
-
继承(Inheritance):通过结构体嵌套实现
-
多态(Polymorphism):通过函数指针实现动态分派
3.1.2 C语言OOP核心实现技术
1. 类的封装与信息隐藏 使用不透明指针(opaque pointer)隐藏实现细节。
c
复制
// animal.h - 公共接口
#ifndef ANIMAL_H
#define ANIMAL_H
// 前向声明,具体定义在.c文件中
typedef struct Animal Animal;
// 构造函数
Animal* animal_create(const char* name, int age);
// 析构函数
void animal_destroy(Animal* animal);
// 公共方法
void animal_set_name(Animal* animal, const char* name);
const char* animal_get_name(const Animal* animal);
void animal_set_age(Animal* animal, int age);
int animal_get_age(const Animal* animal);
// 虚方法(通过函数指针实现多态)
void animal_make_sound(const Animal* animal);
void animal_move(const Animal* animal, int distance);
void animal_eat(const Animal* animal, const char* food);
#endif // ANIMAL_H
// animal.c - 私有实现
#include "animal.h"
#include <stdlib.h>
#include <string.h>
// 虚函数表结构
typedef struct {
void (*make_sound)(const Animal*);
void (*move)(const Animal*, int);
void (*eat)(const Animal*, const char*);
} AnimalVTable;
// 实际类定义(对外隐藏)
struct Animal {
char* name;
int age;
AnimalVTable* vtable; // 虚函数表指针
};
// 默认实现(基类行为)
static void default_make_sound(const Animal* animal) {
printf("%s: 发出未知声音\n", animal->name);
}
static void default_move(const Animal* animal, int distance) {
printf("%s: 移动了 %d 米\n", animal->name, distance);
}
static void default_eat(const Animal* animal, const char* food) {
printf("%s: 吃了 %s\n", animal->name, food);
}
// 基类构造函数
Animal* animal_create(const char* name, int age) {
Animal* animal = (Animal*)calloc(1, sizeof(Animal));
animal->name = strdup(name);
animal->age = age;
// 设置默认虚函数表
static AnimalVTable default_vtable = {
.make_sound = default_make_sound,
.move = default_move,
.eat = default_eat
};
animal->vtable = &default_vtable;
return animal;
}
// 析构函数
void animal_destroy(Animal* animal) {
if (animal) {
free(animal->name);
free(animal);
}
}
// 访问器方法
void animal_set_name(Animal* animal, const char* name) {
if (animal && name) {
free(animal->name);
animal->name = strdup(name);
}
}
const char* animal_get_name(const Animal* animal) {
return animal ? animal->name : "NULL";
}
void animal_set_age(Animal* animal, int age) {
if (animal) animal->age = age;
}
int animal_get_age(const Animal* animal) {
return animal ? animal->age : 0;
}
// 虚方法调用(通过函数指针实现动态分派)
void animal_make_sound(const Animal* animal) {
if (animal && animal->vtable->make_sound) {
animal->vtable->make_sound(animal);
}
}
void animal_move(const Animal* animal, int distance) {
if (animal && animal->vtable->move) {
animal->vtable->move(animal, distance);
}
}
void animal_eat(const Animal* animal, const char* food) {
if (animal && animal->vtable->eat) {
animal->vtable->eat(animal, food);
}
}
2. 继承实现 通过结构体嵌套和类型转换实现继承。
c
复制
// dog.h - 派生类接口
#ifndef DOG_H
#define DOG_H
#include "animal.h"
// Dog继承自Animal
typedef struct Dog Dog;
// Dog构造函数
Dog* dog_create(const char* name, int age, const char* breed);
// 析构函数
void dog_destroy(Dog* dog);
// Dog特有方法
void dog_set_breed(Dog* dog, const char* breed);
const char* dog_get_breed(const Dog* dog);
void dog_bark(const Dog* dog);
// 从Animal继承的方法(通过宏或内联函数转发)
static inline const char* dog_get_name(const Dog* dog) {
return animal_get_name((const Animal*)dog);
}
static inline void dog_make_sound(const Dog* dog) {
animal_make_sound((const Animal*)dog);
}
#endif // DOG_H
// dog.c - 派生类实现
#include "dog.h"
#include <stdlib.h>
#include <string.h>
// Dog类定义(包含基类)
struct Dog {
Animal base; // 基类对象(必须放在第一个位置)
char* breed; // 派生类新增成员
};
// Dog的虚函数实现
static void dog_make_sound_impl(const Animal* animal) {
const Dog* dog = (const Dog*)animal; // 向下转型
printf("%s (品种: %s): 汪汪汪!\n", dog->base.name, dog->breed);
}
static void dog_move_impl(const Animal* animal, int distance) {
const Dog* dog = (const Dog*)animal;
printf("%s 欢快地跑了 %d 米\n", dog->base.name, distance);
}
// Dog虚函数表
static AnimalVTable dog_vtable = {
.make_sound = dog_make_sound_impl,
.move = dog_move_impl,
.eat = default_eat // 使用基类默认实现
};
// Dog构造函数
Dog* dog_create(const char* name, int age, const char* breed) {
Dog* dog = (Dog*)calloc(1, sizeof(Dog));
// 初始化基类部分
dog->base.name = strdup(name);
dog->base.age = age;
dog->base.vtable = &dog_vtable; // 覆盖虚函数表
// 初始化派生类部分
dog->breed = strdup(breed);
return dog;
}
// Dog析构函数
void dog_destroy(Dog* dog) {
if (dog) {
free(dog->breed);
animal_destroy(&dog->base); // 调用基类析构
}
}
// Dog特有方法
void dog_set_breed(Dog* dog, const char* breed) {
if (dog && breed) {
free(dog->breed);
dog->breed = strdup(breed);
}
}
const char* dog_get_breed(const Dog* dog) {
return dog ? dog->breed : "NULL";
}
void dog_bark(const Dog* dog) {
if (dog) {
printf("%s: 汪汪!\n", dog->base.name);
}
}
3. 多重继承(Mixin模式) C语言可以通过结构体组合实现多重继承。
c
复制
// swimmable.h - 可游泳能力接口
#ifndef SWIMMABLE_H
#define SWIMMABLE_H
typedef struct {
void (*swim)(void* obj, int distance);
} SwimmableVTable;
typedef struct {
SwimmableVTable* vtable;
} Swimmable;
#endif // SWIMMABLE_H
// golden_retriever.h - 多重继承
#include "dog.h"
#include "swimmable.h"
typedef struct GoldenRetriever {
Dog dog; // 继承Dog(间接继承Animal)
Swimmable swimmable; // 混入Swimmable能力
int water_resistance; // 特有属性
} GoldenRetriever;
// 游泳实现
static void golden_swim(void* obj, int distance) {
GoldenRetriever* retriever = (GoldenRetriever*)obj;
printf("%s 游泳了 %d 米,防水等级: %d\n",
retriever->dog.base.name, distance, retriever->water_resistance);
}
// 创建金毛
GoldenRetriever* golden_retriever_create(const char* name, int age) {
GoldenRetriever* gr = (GoldenRetriever*)calloc(1, sizeof(GoldenRetriever));
// 初始化Dog部分
gr->dog.base.name = strdup(name);
gr->dog.base.age = age;
gr->dog.base.vtable = &dog_vtable; // 使用Dog的虚表
// 初始化Swimmable部分
static SwimmableVTable swim_vtable = {golden_swim};
gr->swimmable.vtable = &swim_vtable;
gr->water_resistance = 10;
return gr;
}
4. 泛型编程 通过void指针和回调函数实现类似C++模板的泛型。
c
复制
// generic_list.h
#ifndef GENERIC_LIST_H
#define GENERIC_LIST_H
typedef struct ListNode {
void* data;
struct ListNode* next;
} ListNode;
typedef struct {
ListNode* head;
ListNode* tail;
size_t size;
// 泛型操作函数
void* (*copy_func)(const void*); // 数据复制
void (*free_func)(void*); // 数据释放
int (*compare_func)(const void*, const void*); // 比较
} GenericList;
// 创建泛型列表
GenericList* list_create(void* (*copy)(const void*),
void (*free_func)(void*),
int (*compare)(const void*, const void*)) {
GenericList* list = (GenericList*)calloc(1, sizeof(GenericList));
list->copy_func = copy;
list->free_func = free_func;
list->compare_func = compare;
return list;
}
// 泛型插入
void list_push_back(GenericList* list, const void* data) {
ListNode* node = (ListNode*)malloc(sizeof(ListNode));
node->data = list->copy_func ? list->copy_func(data) : (void*)data;
node->next = NULL;
if (list->tail) {
list->tail->next = node;
} else {
list->head = node;
}
list->tail = node;
list->size++;
}
// 泛型查找
void* list_find(GenericList* list, const void* key) {
ListNode* node = list->head;
while (node) {
if (list->compare_func(key, node->data) == 0) {
return node->data;
}
node = node->next;
}
return NULL;
}
#endif // GENERIC_LIST_H
3.1.3 经典OO设计模式实现
1. 工厂模式(Factory) 根据输入动态创建不同子类对象。
c
复制
// factory.h
#ifndef FACTORY_H
#define FACTORY_H
#include "animal.h"
// 工厂函数类型
typedef Animal* (*AnimalFactory)(const char* name, int age, const char* extra);
// 工厂注册表
typedef struct {
const char* type_name;
AnimalFactory factory_func;
} FactoryEntry;
// 动物工厂
typedef struct AnimalFactoryManager {
FactoryEntry* entries;
size_t count;
size_t capacity;
} AnimalFactoryManager;
// 全局工厂管理器
AnimalFactoryManager g_factory = {0};
// 注册工厂
void factory_register(const char* type, AnimalFactory func) {
if (g_factory.count >= g_factory.capacity) {
g_factory.capacity = g_factory.capacity ? g_factory.capacity * 2 : 10;
g_factory.entries = (FactoryEntry*)realloc(g_factory.entries,
sizeof(FactoryEntry) * g_factory.capacity);
}
g_factory.entries[g_factory.count++] = (FactoryEntry){type, func};
}
// 创建动物(工厂方法)
Animal* animal_factory_create(const char* type, const char* name, int age) {
for (size_t i = 0; i < g_factory.count; i++) {
if (strcmp(g_factory.entries[i].type_name, type) == 0) {
return g_factory.entries[i].factory_func(name, age, NULL);
}
}
return NULL; // 未知类型
}
// 具体工厂函数
Animal* dog_factory(const char* name, int age, const char* breed) {
return (Animal*)dog_create(name, age, breed ? breed : "Unknown");
}
#endif // FACTORY_H
2. 观察者模式(Observer) 实现事件订阅和通知机制。
c
复制
// observer.h
#ifndef OBSERVER_H
#define OBSERVER_H
#include "generic_list.h"
// 观察者接口
typedef struct Observer {
void (*update)(struct Observer* self, void* data);
void* user_data;
} Observer;
// 主题(被观察者)
typedef struct Subject {
GenericList* observers; // 观察者列表
void* state;
void (*attach)(struct Subject*, Observer* observer);
void (*detach)(struct Subject*, Observer* observer);
void (*notify)(struct Subject*);
} Subject;
// 实现函数
static void subject_attach(Subject* subj, Observer* observer) {
list_push_back(subj->observers, observer);
}
static void subject_detach(Subject* subj, Observer* observer) {
// 从列表中移除
}
static void subject_notify(Subject* subj) {
ListNode* node = subj->observers->head;
while (node) {
Observer* obs = (Observer*)node->data;
obs->update(obs, subj->state);
node = node->next;
}
}
// 创建主题
Subject* subject_create() {
Subject* subj = (Subject*)calloc(1, sizeof(Subject));
subj->observers = list_create(NULL, NULL, NULL);
subj->attach = subject_attach;
subj->detach = subject_detach;
subj->notify = subject_notify;
return subj;
}
#endif // OBSERVER_H
3. 策略模式(Strategy) 运行时切换算法。
c
复制
// strategy.h
#ifndef STRATEGY_H
#define STRATEGY_H
// 排序策略接口
typedef struct SortStrategy {
void (*sort)(int* array, size_t size);
const char* name;
} SortStrategy;
// 具体策略:冒泡排序
static void bubble_sort(int* arr, size_t size) {
for (size_t i = 0; i < size - 1; i++) {
for (size_t j = 0; j < size - i - 1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
static SortStrategy bubble_strategy = {bubble_sort, "Bubble Sort"};
// 具体策略:快速排序
static void quick_sort_recursive(int* arr, int left, int right) {
if (left >= right) return;
int pivot = arr[left];
int i = left, j = right;
while (i < j) {
while (i < j && arr[j] >= pivot) j--;
arr[i] = arr[j];
while (i < j && arr[i] <= pivot) i++;
arr[j] = arr[i];
}
arr[i] = pivot;
quick_sort_recursive(arr, left, i - 1);
quick_sort_recursive(arr, i + 1, right);
}
static void quick_sort(int* arr, size_t size) {
quick_sort_recursive(arr, 0, size - 1);
}
static SortStrategy quick_strategy = {quick_sort, "Quick Sort"};
// 上下文:使用策略的类
typedef struct Sorter {
SortStrategy* strategy;
void (*set_strategy)(struct Sorter*, SortStrategy*);
void (*sort)(struct Sorter*, int* array, size_t size);
} Sorter;
void sorter_set_strategy(Sorter* sorter, SortStrategy* strategy) {
sorter->strategy = strategy;
}
void sorter_sort(Sorter* sorter, int* array, size_t size) {
printf("使用 %s 进行排序\n", sorter->strategy->name);
sorter->strategy->sort(array, size);
}
Sorter* sorter_create(SortStrategy* initial) {
Sorter* s = (Sorter*)calloc(1, sizeof(Sorter));
s->strategy = initial;
s->set_strategy = sorter_set_strategy;
s->sort = sorter_sort;
return s;
}
#endif // STRATEGY_H
3.1.4 LVOOP等效实现
将LabVIEW面向对象概念映射到C语言:
c
复制
// 类比LabVIEW类库
typedef struct LVClass {
const char* class_name;
struct LVClass* parent; // 继承链
// 私有数据
size_t private_data_size;
void* default_private_data;
// 方法列表
struct LVMethod {
const char* method_name;
void* (*method_ptr)(void* instance, void* params);
bool is_dynamic_dispatch;
}* methods;
size_t method_count;
} LVClass;
// 创建对象实例
void* lv_create_object(const LVClass* class) {
// 分配内存:对象头 + 私有数据
uint8_t* obj = (uint8_t*)calloc(1, sizeof(void*) + class->private_data_size);
// 存储类指针(用于运行时类型识别)
*(const LVClass**)obj = class;
// 复制默认私有数据
memcpy(obj + sizeof(void*), class->default_private_data,
class->private_data_size);
return obj;
}
// 动态分派调用
void* lv_invoke_method(void* obj, const char* method_name, void* params) {
const LVClass* class = *(const LVClass**)obj;
// 查找方法(支持继承链查找)
while (class) {
for (size_t i = 0; i < class->method_count; i++) {
if (strcmp(class->methods[i].method_name, method_name) == 0) {
return class->methods[i].method_ptr(obj, params);
}
}
class = class->parent; // 向上查找父类
}
return NULL; // 方法未找到
}
3.2 面向操作者(Actor)的设计模式
3.2.1 概述
面向Actor的设计模式是利用Actor模型(例如Actor Framework)的一类软件设计模式。在C语言中,Actor是构建大型、高度并行化、可扩展系统的强大工具。Actor模型的核心思想是:
-
隔离状态:每个Actor拥有私有状态,不共享内存
-
消息传递:Actor之间只通过异步消息通信
-
单线程执行:每个Actor串行处理消息,避免并发问题
-
监督机制:Actor可以监控其他Actor,实现容错
从数据流转向消息流在传统C语言编程中,函数调用用于描述模块的执行逻辑。对于大型系统,这种方式难以描述模块之间的通信与协作。Actor模型通过明确的消息传递机制来组织模块间的交互,适用于模块众多、交互复杂的系统。数据流依然适合组件内部或生命周期短、逻辑简单的进程。
3.2.2 Actor Framework设计模式
1. 基础Actor实现
c
复制
// actor.h
#ifndef ACTOR_H
#define ACTOR_H
#include "message_queue.h"
#include <pthread.h>
#include <stdatomic.h>
// Actor状态
typedef enum {
ACTOR_STATE_IDLE,
ACTOR_STATE_RUNNING,
ACTOR_STATE_BLOCKED,
ACTOR_STATE_TERMINATED,
ACTOR_STATE_FAILED
} ActorState;
// Actor抽象基类
typedef struct Actor {
// 身份标识
uint64_t actor_id;
const char* actor_name;
// 消息邮箱
MessageQueue* mailbox;
size_t max_mailbox_size;
// 执行状态
ActorState state;
pthread_t thread;
atomic_bool running;
// 监督关系
struct Actor* supervisor; // 监督者
GenericList* children; // 子Actor列表
// 生命周期管理
void (*pre_start)(struct Actor*); // 启动前回调
void (*post_stop)(struct Actor*); // 停止后回调
// 消息处理(虚函数)
void (*receive)(struct Actor*, const Message* msg);
// 监督策略
void (*supervisor_strategy)(struct Actor*, struct Actor* child,
const Message* failure_msg);
// 统计信息
uint64_t messages_received;
uint64_t messages_processed;
uint64_t failures_count;
// 用户自定义数据
void* user_data;
} Actor;
// 创建Actor
Actor* actor_create(size_t mailbox_size) {
Actor* actor = (Actor*)calloc(1, sizeof(Actor));
actor->actor_id = atomic_fetch_add(&g_actor_id_counter, 1);
actor->state = ACTOR_STATE_IDLE;
actor->max_mailbox_size = mailbox_size ? mailbox_size : 1000;
MessageQueueConfig cfg = {
.max_size = actor->max_mailbox_size,
.enable_priority = true
};
actor->mailbox = message_queue_create(&cfg);
actor->children = list_create(NULL, NULL, NULL);
atomic_init(&actor->running, false);
return actor;
}
// Actor主循环
static void* actor_thread_main(void* arg) {
Actor* actor = (Actor*)arg;
// 调用生命周期钩子
if (actor->pre_start) {
actor->pre_start(actor);
}
actor->state = ACTOR_STATE_RUNNING;
printf("Actor %s (ID: %lu) 开始运行\n", actor->actor_name, actor->actor_id);
while (atomic_load(&actor->running)) {
Message* msg = message_queue_dequeue(actor->mailbox, 100); // 100ms超时
if (msg) {
actor->messages_received++;
// 特殊系统消息处理
if (msg->type == MSG_SHUTDOWN) {
printf("Actor %s 收到停止指令\n", actor->actor_name);
break;
}
// 处理消息
if (actor->receive) {
try {
actor->receive(actor, msg);
actor->messages_processed++;
} catch {
actor->failures_count++;
// 通知监督者
if (actor->supervisor) {
Message* failure_msg = message_create(MSG_ERROR,
&actor->actor_id, sizeof(uint64_t));
actor->supervisor->mailbox->enqueue(
actor->supervisor->mailbox, failure_msg);
}
}
}
message_destroy(msg);
}
}
actor->state = ACTOR_STATE_TERMINATED;
// 停止所有子Actor
list_foreach(actor->children, stop_child_actor);
// 调用停止钩子
if (actor->post_stop) {
actor->post_stop(actor);
}
return NULL;
}
// 启动Actor
void actor_start(Actor* actor) {
atomic_store(&actor->running, true);
actor->state = ACTOR_STATE_IDLE;
pthread_create(&actor->thread, NULL, actor_thread_main, actor);
}
// 发送消息(异步)
void actor_send(Actor* target, const Message* msg) {
Message* msg_copy = message_clone(msg);
msg_copy->target_id = target->actor_id;
message_queue_enqueue(target->mailbox, msg_copy);
}
// 请求-响应模式
Message* actor_ask(Actor* target, const Message* request, int timeout_ms) {
// 创建临时响应队列
MessageQueue* temp_queue = message_queue_create(&(MessageQueueConfig){1});
// 发送请求(包含响应地址)
Message* req = message_clone(request);
req->source_id = target->actor_id; // 简化为Actor ID
req->extra_data = temp_queue; // 响应队列
actor_send(target, req);
// 等待响应
Message* response = message_queue_dequeue(temp_queue, timeout_ms);
message_queue_destroy(temp_queue);
return response;
}
#endif // ACTOR_H
2. 监督树(Supervision Tree) 监督树是Actor模型的核心,提供容错能力。
c
复制
// supervision.h
#ifndef SUPERVISION_H
#define SUPERVISION_H
#include "actor.h"
// 监督策略
typedef enum {
SUPERVISION_ONE_FOR_ONE, // 只重启失败的子Actor
SUPERVISION_ONE_FOR_ALL, // 重启所有子Actor
SUPERVISION_REST_FOR_ONE // 重启失败的及其之后启动的
} SupervisionStrategy;
// 重启策略
typedef enum {
RESTART_ALWAYS, // 总是重启
RESTART_NEVER, // 从不重启
RESTART_MAX_RETRY // 最多重试N次
} RestartPolicy;
// 监督者Actor
typedef struct SupervisorActor {
Actor base; // 继承Actor
SupervisionStrategy strategy;
RestartPolicy restart_policy;
int max_restarts;
int restart_count;
time_t last_failure_time;
} SupervisorActor;
// 默认监督策略:OneForOne
static void one_for_one_strategy(Actor* supervisor, Actor* child,
const Message* failure_msg) {
SupervisorActor* self = (SupervisorActor*)supervisor;
time_t now = time(NULL);
if (difftime(now, self->last_failure_time) > 60.0) {
self->restart_count = 0; // 1分钟内重置计数
}
self->last_failure_time = now;
if (self->restart_policy == RESTART_ALWAYS ||
(self->restart_policy == RESTART_MAX_RETRY &&
self->restart_count < self->max_restarts)) {
printf("监督者 %s: 重启失败的子Actor %s\n",
supervisor->actor_name, child->actor_name);
// 停止子Actor
atomic_store(&child->running, false);
pthread_join(child->thread, NULL);
// 重新启动
actor_start(child);
self->restart_count++;
} else {
printf("监督者 %s: 停止重启子Actor %s\n",
supervisor->actor_name, child->actor_name);
}
}
// 创建监督者
SupervisorActor* supervisor_create(const char* name, size_t mailbox_size) {
SupervisorActor* sup = (SupervisorActor*)actor_create(mailbox_size);
sup->base.actor_name = strdup(name);
sup->base.supervisor_strategy = one_for_one_strategy;
sup->strategy = SUPERVISION_ONE_FOR_ONE;
sup->restart_policy = RESTART_MAX_RETRY;
sup->max_restarts = 5;
sup->restart_count = 0;
return sup;
}
// 添加子Actor到监督
void supervisor_add_child(SupervisorActor* sup, Actor* child) {
child->supervisor = (Actor*)sup;
list_push_back(sup->base.children, child);
}
#endif // SUPERVISION_H
3. 路由器Actor(负载均衡)
c
复制
// router.h
#ifndef ROUTER_H
#define ROUTER_H
#include "actor.h"
// 路由策略
typedef enum {
ROUTE_ROUND_ROBIN, // 轮询
ROUTE_RANDOM, // 随机
ROUTE_LEAST_LOADED, // 最少负载
ROUTE_HASH_BASED // 基于哈希
} RoutingStrategy;
// 路由器Actor
typedef struct RouterActor {
Actor base;
RoutingStrategy strategy;
Actor** workers; // 工作Actor数组
size_t worker_count;
size_t current_index; // 轮询索引
uint64_t total_messages;
} RouterActor;
// 轮询路由
static Actor* round_robin_route(RouterActor* router) {
Actor* worker = router->workers[router->current_index];
router->current_index = (router->current_index + 1) % router->worker_count;
return worker;
}
// 接收重载:分发消息
static void router_receive(Actor* base, const Message* msg) {
RouterActor* router = (RouterActor*)base;
// 选择目标工作Actor
Actor* target = round_robin_route(router);
// 转发消息
actor_send(target, msg);
router->total_messages++;
}
// 创建路由器
RouterActor* router_create(const char* name, RoutingStrategy strategy) {
RouterActor* router = (RouterActor*)actor_create(10000);
router->base.actor_name = strdup(name);
router->base.receive = router_receive;
router->strategy = strategy;
router->workers = NULL;
router->worker_count = 0;
router->current_index = 0;
router->total_messages = 0;
return router;
}
// 添加工作Actor
void router_add_worker(RouterActor* router, Actor* worker) {
router->workers = (Actor**)realloc(router->workers,
sizeof(Actor*) * (router->worker_count + 1));
router->workers[router->worker_count++] = worker;
}
#endif // ROUTER_H
4. 完整Actor系统示例:Web服务器
c
复制
// web_server.c
#include "actor.h"
#include "router.h"
#include "supervision.h"
// 全局Actor系统
ActorSystem g_actor_system;
// HTTP请求结构
typedef struct HttpRequest {
char method[8];
char path[256];
char version[16];
char headers[1024];
char body[4096];
int client_fd;
} HttpRequest;
// 连接接收Actor
typedef struct AcceptorActor {
Actor base;
int listen_port;
int listen_fd;
RouterActor* router; // 请求路由器
} AcceptorActor;
void acceptor_receive(Actor* base, const Message* msg) {
AcceptorActor* acceptor = (AcceptorActor*)base;
if (msg->type == MSG_INIT) {
// 初始化监听socket
acceptor->listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bind(acceptor->listen_fd, ...);
listen(acceptor->listen_fd, 100);
printf("Acceptor监听端口 %d\n", acceptor->listen_port);
}
// 接受连接
while (1) {
int client_fd = accept(acceptor->listen_fd, NULL, NULL);
// 创建HTTP请求消息
Message* req_msg = message_create(MSG_HTTP_REQUEST, &client_fd, sizeof(int));
req_msg->priority = MSG_PRIO_HIGH;
// 路由到工作Actor
Actor* worker = round_robin_route(acceptor->router);
actor_send(worker, req_msg);
}
}
// 工作Actor(处理HTTP请求)
typedef struct WorkerActor {
Actor base;
int worker_id;
HttpRequest current_request;
} WorkerActor;
void worker_receive(Actor* base, const Message* msg) {
WorkerActor* worker = (WorkerActor*)base;
if (msg->type == MSG_HTTP_REQUEST) {
int client_fd = *(int*)msg->data;
// 读取HTTP请求
read_http_request(client_fd, &worker->current_request);
// 处理请求
const char* response = process_request(&worker->current_request);
// 发送响应
send(client_fd, response, strlen(response), 0);
close(client_fd);
printf("Worker %d 处理请求 %s\n", worker->worker_id, worker->current_request.path);
}
}
int main() {
// 初始化Actor系统
actor_system_init(&g_actor_system);
// 创建监督者
SupervisorActor* supervisor = supervisor_create("WebServerSupervisor", 10000);
// 创建路由器
RouterActor* router = router_create("RequestRouter", ROUTE_ROUND_ROBIN);
supervisor_add_child(supervisor, (Actor*)router);
// 创建Worker Actor池(8个工作线程)
const int WORKER_COUNT = 8;
for (int i = 0; i < WORKER_COUNT; i++) {
WorkerActor* worker = (WorkerActor*)actor_create(500);
worker->base.actor_name = malloc(32);
snprintf(worker->base.actor_name, 32, "Worker-%d", i);
worker->worker_id = i;
worker->base.receive = worker_receive;
actor_start((Actor*)worker);
router_add_worker(router, (Actor*)worker);
supervisor_add_child(supervisor, (Actor*)worker);
}
// 创建Acceptor
AcceptorActor* acceptor = (AcceptorActor*)actor_create(1000);
acceptor->base.actor_name = "HTTPAcceptor";
acceptor->listen_port = 8080;
acceptor->router = router;
acceptor->base.receive = acceptor_receive;
supervisor_add_child(supervisor, (Actor*)acceptor);
// 启动所有Actor
actor_start((Actor*)supervisor);
actor_start((Actor*)router);
actor_start((Actor*)acceptor);
printf("Web服务器启动完成,监听8080端口\n");
// 等待系统运行
while (1) {
sleep(10);
// 打印统计信息
print_actor_stats((Actor*)supervisor);
}
return 0;
}
3.2.3 Actor模式最佳实践
1. 消息设计原则
-
消息应该是不可变的
-
避免大消息,大数据使用引用传递
-
为不同优先级使用不同消息类型
2. Actor粒度
-
每个Actor应该只做一件事(单一职责)
-
避免创建过多Actor(线程开销)
-
对于IO密集型,Actor数量可以多于CPU核心数
3. 错误处理
-
永远不要让Actor异常退出
-
使用监督树实现容错
-
为不同类型的失败设计不同的重启策略
4. 性能优化
-
使用零拷贝消息传递
-
批量处理消息减少上下文切换
-
使用Lock-Free队列提高吞吐量
c
复制
// Lock-Free队列实现
typedef struct LockFreeQueue {
_Atomic(Node*) head;
_Atomic(Node*) tail;
_Atomic(size_t) count;
} LockFreeQueue;
bool lf_queue_produce(LockFreeQueue* queue, void* data) {
Node* node = (Node*)malloc(sizeof(Node));
node->data = data;
node->next = ATOMIC_VAR_INIT(NULL);
Node* tail = atomic_load(&queue->tail);
Node* tail_next = NULL;
// 尝试添加到尾部
do {
tail = atomic_load(&queue->tail);
tail_next = atomic_load(&tail->next);
if (tail_next != NULL) {
// 帮助更新tail
atomic_compare_exchange_weak(&queue->tail, &tail, tail_next);
}
} while (tail_next != NULL);
// 链接新节点
if (atomic_compare_exchange_strong(&tail->next, &tail_next, node)) {
atomic_compare_exchange_weak(&queue->tail, &tail, node);
atomic_fetch_add(&queue->count, 1);
return true;
}
free(node);
return false;
}
总结
本文详细阐述了C语言中从基础到高级的设计模式实现,涵盖了:
基本设计模式(单循环架构)
-
状态机模式:通过枚举、函数指针表实现清晰的状态转移逻辑,适用于协议解析、设备控制等场景
-
事件处理模式:基于消息队列和回调机制实现异步事件驱动,适用于GUI和I/O密集型应用
基本设计模式(多循环架构)
-
主从模式:通过多线程+同步原语实现任务并行,主线程协调,从线程执行具体任务
-
生产者消费者模式:通过环形缓冲区解耦数据生产与消费,解决速率不匹配问题
中级设计模式
- QMH(队列消息处理器):融合事件处理与生产消费模式,通过消息队列实现模块间松耦合通信,是构建中大型系统的基础
高级设计模式
-
面向对象模式:通过结构体+函数指针模拟类、继承、多态,实现经典OO设计模式
-
Actor模式:通过消息传递和Actor隔离实现高度并发、容错性强的分布式系统
每种模式都提供了完整的C语言实现,包含:
-
清晰的数据结构定义
-
线程安全的同步机制
-
详细的代码注释
-
实际应用示例
-
性能优化建议
设计模式选择指南:
表格
复制
| 应用场景 | 推荐模式 | 原因 |
|---|---|---|
| 简单状态控制 | 状态机 | 逻辑清晰,易于调试 |
| GUI应用 | 事件处理+QMH | 响应式架构,模块解耦 |
| 数据采集系统 | 生产者消费者 | 缓冲数据,平滑处理 |
| 多任务并行 | 主从模式 | 任务分发,统一管理 |
| 复杂业务逻辑 | 面向对象 | 代码复用,易于扩展 |
| 高并发服务 | Actor模式 | 隔离故障,弹性伸缩 |
性能考量:
-
状态机:O(1)转移,内存占用小
-
消息队列:锁竞争是瓶颈,可使用Lock-Free优化
-
Actor:线程切换开销,适合粗粒度任务
-
OOP:函数指针调用有轻微性能损失
代码可维护性:
-
所有模式都强调低耦合高内聚
-
消息传递比共享内存更容易推理
-
明确的生命周期管理防止资源泄漏
掌握这些设计模式后,开发者可以构建出结构清晰、可维护性强、可扩展性好的C语言应用程序。建议从简单的状态机开始实践,逐步过渡到复杂的消息驱动架构,最终根据项目需求选择合适的模式组合。