diff --git a/release/inc/list.h b/release/inc/list.h index 20c6465..f5c03f3 100644 --- a/release/inc/list.h +++ b/release/inc/list.h @@ -1,9 +1,9 @@ /** * @file list.h - * @brief 内核风格侵入式双向循环链表(纯头文件,C/C++ 兼容) - * - * 用法:将 struct list_head 嵌入你的结构体,通过 list_entry 取回宿主指针。 - * 所有操作 O(1),遍历 O(n)。C++ 兼容:不用 new/class/typeof 等关键字。 + * @brief Linux 内核风格侵入式双向循环链表(纯头文件,C/C++ 兼容) + * @details 将 struct list_head 嵌入宿主结构体,通过 list_entry 取回宿主指针。 + * 所有操作 O(1),遍历 O(n)。 + * C++ 兼容:变量名不使用 new/class/typeof 等关键字。 */ #ifndef _LIST_H_ @@ -16,7 +16,7 @@ extern "C" { #endif -/* ---- 节点 ---- */ +/* ---- 链表节点 ---- */ struct list_head { struct list_head *next; @@ -27,13 +27,16 @@ struct list_head #define LIST_HEAD_INIT(n) { &(n), &(n) } #define LIST_HEAD(n) struct list_head n = LIST_HEAD_INIT(n) +/** + * @brief 运行时初始化链表头 + */ static inline void INIT_LIST_HEAD(struct list_head *h) { h->next = h; h->prev = h; } -/* ---- 内部:在 prev 和 next 之间插入 node ---- */ +/* ---- 内部辅助:在 prev 和 next 之间插入 node ---- */ static inline void __list_add(struct list_head *node, struct list_head *prev, struct list_head *next) @@ -44,7 +47,7 @@ static inline void __list_add(struct list_head *node, prev->next = node; } -/* ---- 内部:删除 prev 和 next 之间的节点 ---- */ +/* ---- 内部辅助:移除 prev 和 next 之间的节点 ---- */ static inline void __list_del(struct list_head *prev, struct list_head *next) { @@ -52,43 +55,54 @@ static inline void __list_del(struct list_head *prev, prev->next = next; } -/* ---- 添加 ---- */ +/* ---- 添加操作 ---- */ + +/** 头插法:插入到 head 之后(作为第一个元素) */ static inline void list_add(struct list_head *node, struct list_head *head) { __list_add(node, head, head->next); } +/** 尾插法:插入到 head 之前(作为最后一个元素) */ static inline void list_add_tail(struct list_head *node, struct list_head *head) { __list_add(node, head->prev, head); } -/* ---- 删除 ---- */ +/* ---- 删除操作 ---- */ + +/** 从链表移除节点(不释放内存) */ static inline void list_del(struct list_head *e) { __list_del(e->prev, e->next); } +/** 移除并重新初始化节点(安全删除,防止悬空指针) */ static inline void list_del_init(struct list_head *e) { __list_del(e->prev, e->next); INIT_LIST_HEAD(e); } -/* ---- 移动 ---- */ +/* ---- 移动操作 ---- */ + +/** 将节点移动到新链表头部 */ static inline void list_move(struct list_head *l, struct list_head *h) { __list_del(l->prev, l->next); list_add(l, h); } +/** 将节点移动到新链表尾部 */ static inline void list_move_tail(struct list_head *l, struct list_head *h) { __list_del(l->prev, l->next); list_add_tail(l, h); } -/* ---- 替换 ---- */ +/* ---- 替换操作 ---- */ + +/** 用 node 替换 old */ static inline void list_replace(struct list_head *old, struct list_head *node) { node->next = old->next; @@ -97,6 +111,7 @@ static inline void list_replace(struct list_head *old, struct list_head *node) node->prev->next = node; } +/** 替换后初始化被替换节点 */ static inline void list_replace_init(struct list_head *old, struct list_head *node) { @@ -104,43 +119,56 @@ static inline void list_replace_init(struct list_head *old, INIT_LIST_HEAD(old); } -/* ---- 判断 ---- */ +/* ---- 判断操作 ---- */ + +/** 判断链表是否为空 */ static inline int list_empty(const struct list_head *h) { return h->next == h; } +/** 判断节点是否已链入链表 */ static inline int list_is_linked(const struct list_head *e) { return e->next != e; } -/* ---- 宿主指针 ---- */ +/* ---- 节点 ↔ 宿主指针转换 ---- */ + +/** 从链表节点指针取回宿主结构体指针 */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr) - offsetof(type, member))) +/** 获取第一个宿主元素 */ #define list_first_entry(h, type, member) \ list_entry((h)->next, type, member) +/** 获取最后一个宿主元素 */ #define list_last_entry(h, type, member) \ list_entry((h)->prev, type, member) +/** 安全获取第一个元素(链表空返回 NULL) */ #define list_first_entry_or_null(h, type, member) \ (list_empty(h) ? NULL : list_first_entry(h, type, member)) -/* ---- 遍历 ---- */ +/* ---- 遍历操作 ---- */ + +/** 遍历链表节点(仅获取 struct list_head 指针) */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) +/** 安全遍历节点(可在遍历中删除 pos) */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) +/** 遍历宿主元素 */ #define list_for_each_entry(pos, head, member) \ for (pos = list_first_entry(head, __typeof__(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, __typeof__(*pos), member)) +/** 安全遍历宿主元素(可在遍历中删除 pos) */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_first_entry(head, __typeof__(*pos), member), \ n = list_entry(pos->member.next, __typeof__(*pos), member); \ @@ -148,7 +176,9 @@ static inline int list_is_linked(const struct list_head *e) pos = n, \ n = list_entry(n->member.next, __typeof__(*n), member)) -/* ---- 拼接 ---- */ +/* ---- 拼接操作 ---- */ + +/** 将 src 链表拼接到 dst 头部,src 被清空 */ static inline void list_splice_init(struct list_head *src, struct list_head *dst) { @@ -169,4 +199,5 @@ static inline void list_splice_init(struct list_head *src, #ifdef __cplusplus } #endif -#endif + +#endif /* _LIST_H_ */ diff --git a/release/inc/myBase.h b/release/inc/myBase.h index 002e929..10a2c5d 100644 --- a/release/inc/myBase.h +++ b/release/inc/myBase.h @@ -1,7 +1,8 @@ /** * @file myBase.h - * @brief Public base definitions — shared macros, types, constants - * @details Written from scratch, functionally aligned with RTU original. + * @brief 公共基础定义 — 所有模块共享的宏、类型、常量 + * @details 从零编写,功能对齐 RTU 原工程。 + * 包含:终端颜色、字节序转换、数据类型常量等。 */ #ifndef _MY_BASE_H_ @@ -22,7 +23,7 @@ extern "C" { #endif -/* === Terminal colors === */ +/* === 终端颜色码 === */ #define COLOR_RESET "\033[0m" #define COLOR_RED "\033[31m" #define COLOR_GREEN "\033[32m" @@ -32,14 +33,14 @@ extern "C" #define COLOR_CYAN "\033[36m" #define COLOR_WHITE "\033[37m" -/* === Short filename (strip path prefix, cross-platform) === */ +/* === 文件名缩写(去除路径前缀,跨平台兼容) === */ #if defined(__linux__) #define __SHORT_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) #else #define __SHORT_FILE__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__) #endif -/* === Console log macros (usable before liblog is loaded) === */ +/* === 简易控制台日志宏(liblog 加载前可用) === */ #define MY_LOG(color, level, fmt, ...) \ do \ { \ @@ -50,42 +51,42 @@ extern "C" #define MY_LOG_I(fmt, ...) MY_LOG(COLOR_WHITE, "INFO", fmt, ##__VA_ARGS__) #define MY_LOG_E(fmt, ...) MY_LOG(COLOR_RED, "ERROR", fmt, ##__VA_ARGS__) -/* === LOCAL modifier (semantic: file-scope only) === */ +/* === LOCAL 修饰符(语义:文件内可见,等价于 static) === */ #ifndef LOCAL #define LOCAL static #endif -/* === Fixed-length string types === */ +/* === 定长字符串类型 === */ #define SHORT_STR_LEN 64 typedef char S_STR[SHORT_STR_LEN]; #define LONG_STR_LEN 128 typedef char L_STR[LONG_STR_LEN]; -/* === Endian swap: uint16 === */ +/* === 字节序转换:uint16 === */ #define BE16_GET(p) ((uint16_t)(((uint8_t *)(p))[0] << 8 | ((uint8_t *)(p))[1])) #define BE16_SET(m, n) ((m)[0] = (uint8_t)((n) >> 8), (m)[1] = (uint8_t)(n)) #define LE16_GET(p) ((uint16_t)(((uint8_t *)(p))[1] << 8 | ((uint8_t *)(p))[0])) #define LE16_SET(m, n) ((m)[0] = (uint8_t)(n), (m)[1] = (uint8_t)((n) >> 8)) -/* === Endian swap: int32 === */ +/* === 字节序转换:int32 === */ #define BE32_GET(p) ((int32_t)(((uint8_t *)(p))[0] << 24 | ((uint8_t *)(p))[1] << 16 | ((uint8_t *)(p))[2] << 8 | ((uint8_t *)(p))[3])) #define BE32_SET(m, n) ((m)[0] = (uint8_t)((n) >> 24), (m)[1] = (uint8_t)((n) >> 16), (m)[2] = (uint8_t)((n) >> 8), (m)[3] = (uint8_t)(n)) #define LE32_GET(p) ((int32_t)(((uint8_t *)(p))[3] << 24 | ((uint8_t *)(p))[2] << 16 | ((uint8_t *)(p))[1] << 8 | ((uint8_t *)(p))[0])) #define LE32_SET(m, n) ((m)[3] = (uint8_t)((n) >> 24), (m)[2] = (uint8_t)((n) >> 16), (m)[1] = (uint8_t)((n) >> 8), (m)[0] = (uint8_t)(n)) -/* === Endian swap: uint64 === */ +/* === 字节序转换:uint64 === */ #define BE64_GET(p) (((uint64_t)(((uint8_t *)(p))[0]) << 56) | ((uint64_t)(((uint8_t *)(p))[1]) << 48) | ((uint64_t)(((uint8_t *)(p))[2]) << 40) | ((uint64_t)(((uint8_t *)(p))[3]) << 32) | ((uint64_t)(((uint8_t *)(p))[4]) << 24) | ((uint64_t)(((uint8_t *)(p))[5]) << 16) | ((uint64_t)(((uint8_t *)(p))[6]) << 8) | ((uint64_t)(((uint8_t *)(p))[7]))) #define LE64_GET(p) (((uint64_t)(((uint8_t *)(p))[7]) << 56) | ((uint64_t)(((uint8_t *)(p))[6]) << 48) | ((uint64_t)(((uint8_t *)(p))[5]) << 40) | ((uint64_t)(((uint8_t *)(p))[4]) << 32) | ((uint64_t)(((uint8_t *)(p))[3]) << 24) | ((uint64_t)(((uint8_t *)(p))[2]) << 16) | ((uint64_t)(((uint8_t *)(p))[1]) << 8) | ((uint64_t)(((uint8_t *)(p))[0]))) #define BE64_SET(m, n) ((m)[0] = (uint8_t)((n) >> 56), (m)[1] = (uint8_t)((n) >> 48), (m)[2] = (uint8_t)((n) >> 40), (m)[3] = (uint8_t)((n) >> 32), (m)[4] = (uint8_t)((n) >> 24), (m)[5] = (uint8_t)((n) >> 16), (m)[6] = (uint8_t)((n) >> 8), (m)[7] = (uint8_t)(n)) #define LE64_SET(m, n) ((m)[7] = (uint8_t)((n) >> 56), (m)[6] = (uint8_t)((n) >> 48), (m)[5] = (uint8_t)((n) >> 40), (m)[4] = (uint8_t)((n) >> 32), (m)[3] = (uint8_t)((n) >> 24), (m)[2] = (uint8_t)((n) >> 16), (m)[1] = (uint8_t)((n) >> 8), (m)[0] = (uint8_t)(n)) -/* === Typed data access === */ +/* === 类型化数据存取 === */ #define GET_BY_TYPE(p, type) (*(type *)(p)) #define SET_BY_TYPE(p, v, type) (*(type *)(p) = *(type *)(v)) -/* === Data type constants (for protocol encode/decode) === */ +/* === 数据类型常量(用于协议编解码) === */ #define DATA_TYPE_B 1 #define DATA_TYPE_S8 43 #define DATA_TYPE_U8 32 diff --git a/release/inc/myLog.h b/release/inc/myLog.h index c6aabdc..1d6f5e8 100644 --- a/release/inc/myLog.h +++ b/release/inc/myLog.h @@ -1,9 +1,9 @@ /** * @file myLog.h * @brief 异步日志系统接口(纯 C) - * @details 提供 INFO/ERROR 两级异步日志,非阻塞写入。 - * 支持控制台彩色输出、文件输出、文件按大小轮转。 - * 首次调用 log_prt 时自动初始化,无需手动 init。 + * @details 支持 INFO/ERROR 两级日志,非阻塞写入。 + * 首次调用 log_prt 时自动初始化(pthread_once 懒启动),无需手动 init。 + * 控制台支持彩色 ANSI 输出,文件支持按大小自动轮转。 */ #ifndef _MY_LOG_H_ @@ -14,25 +14,26 @@ extern "C" { #endif -/** 日志级别:INFO(普通信息) */ +/** 日志级别:INFO(普通信息,白色输出) */ #define LOG_INFO 0 -/** 日志级别:ERROR(错误信息,控制台红色输出) */ + +/** 日志级别:ERROR(错误信息,红色输出) */ #define LOG_ERROR 1 /** - * @brief 手动初始化日志系统(可选,log_prt 自动懒初始化) - * @param dir 日志文件目录路径,传 NULL 则默认 /tmp/logs + * @brief 手动初始化日志系统(可选,首次 log_prt 会自动触发) + * @param dir 日志文件目录路径,传 NULL 则使用默认 /tmp/logs * @return 0 成功 */ int log_init(const char *dir); /** * @brief 核心日志打印函数(非阻塞,消息入队列后立即返回) - * @param level 日志级别 LOG_INFO 或 LOG_ERROR - * @param file 源文件名(通常传 __FILE__) - * @param func 函数名(通常传 __FUNCTION__) - * @param line 行号(通常传 __LINE__) - * @param fmt printf 风格格式化字符串 + * @param level 日志级别(LOG_INFO 或 LOG_ERROR) + * @param file 源文件名(通常传 __FILE__) + * @param func 函数名(通常传 __FUNCTION__) + * @param line 行号(通常传 __LINE__) + * @param fmt printf 格式化字符串 * @param ... 可变参数 */ void log_prt(uint32_t level, const char *file, const char *func, @@ -53,13 +54,13 @@ void log_console_off(void); /** 等待异步队列清空(阻塞直到所有消息写入完成) */ void log_flush(void); -/** 停止工作线程、关闭文件、释放消息池内存 */ +/** 停止工作线程、关闭文件、释放消息池 */ void log_cleanup(void); -/** INFO 级别日志宏 */ +/** INFO 级别便捷日志宏 */ #define LOG_I(fmt, ...) log_prt(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) -/** ERROR 级别日志宏 */ +/** ERROR 级别便捷日志宏 */ #define LOG_E(fmt, ...) log_prt(LOG_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus diff --git a/release/inc/myMd5.h b/release/inc/myMd5.h index f2b547e..0b5f9a2 100644 --- a/release/inc/myMd5.h +++ b/release/inc/myMd5.h @@ -1,7 +1,8 @@ /** * @file myMd5.h - * @brief MD5 message digest (RFC 1321) - * @details Computes 128-bit hash. Supports streaming update. + * @brief MD5 消息摘要算法接口(RFC 1321) + * @details 计算 128 位哈希值,支持流式输入。 + * 提供单次调用便捷函数 md5_string()。 */ #ifndef _MY_MD5_H_ @@ -14,25 +15,41 @@ extern "C" #endif /** - * @brief MD5 context (state + count + pending buffer) + * @brief MD5 计算上下文(状态 + 计数 + 待处理缓冲区) */ typedef struct { - uint32_t state[4]; /* A, B, C, D */ - uint32_t count[2]; /* bit count low/high */ - unsigned char buf[64]; /* pending bytes */ + uint32_t state[4]; /* A, B, C, D 四个 32 位状态寄存器 */ + uint32_t count[2]; /* 位计数(低 32 位, 高 32 位) */ + unsigned char buf[64]; /* 待处理数据缓冲区(64 字节) */ } stru_md5_ctx; -/** Initialize context with magic constants */ +/** + * @brief 初始化 MD5 上下文 + * @param ctx 上下文指针(设置魔数 A=0x67452301 B=0xefcdab89 C=0x98badcfe D=0x10325476) + */ void md5_start(stru_md5_ctx *ctx); -/** Feed data, callable multiple times */ +/** + * @brief 输入待计算数据(可多次调用,支持流式处理) + * @param ctx 上下文指针 + * @param data 数据缓冲区 + * @param len 数据长度(字节) + */ void md5_update(stru_md5_ctx *ctx, const unsigned char *data, int len); -/** Finalize, get 16-byte digest */ +/** + * @brief 完成计算,输出 16 字节 MD5 摘要 + * @param ctx 上下文指针 + * @param result 输出缓冲区(至少 16 字节) + */ void md5_final(stru_md5_ctx *ctx, unsigned char result[16]); -/** One-shot: compute MD5 of string, output 32-char hex (uppercase) */ +/** + * @brief 单次调用便捷函数:计算字符串的 MD5,返回大写十六进制字符串 + * @param input 输入字符串(以 '\0' 结尾) + * @param output 输出缓冲区(至少 33 字节,含结尾 '\0') + */ void md5_string(const char *input, char output[33]); #ifdef __cplusplus diff --git a/release/inc/myTask.h b/release/inc/myTask.h index 0cfacaf..fc093b0 100644 --- a/release/inc/myTask.h +++ b/release/inc/myTask.h @@ -1,11 +1,15 @@ /** * @file myTask.h - * @brief Task framework: timers + events + message queues (C interface) - * @details Based on SPEC §8 analysis. Uses C++ internally. + * @brief 任务框架接口 — 定时器 + 事件 + 消息队列(C 接口) + * @details 基于 SPEC §8 原工程分析。 + * 定时器基于 timerfd + epoll 实现,精确到毫秒。 + * 事件基于位图 + pthread 条件变量实现。 + * 消息队列基于环形缓冲区 + 互斥锁 + 条件变量实现。 */ #ifndef _MY_TASK_H_ #define _MY_TASK_H_ + #include #ifdef __cplusplus @@ -14,130 +18,219 @@ extern "C" #endif /* ================================================================ - * Opaque handles + * 通用定义 * ================================================================ */ -typedef struct stru_task_timer *stru_task_timer_t; -typedef struct stru_task_event *stru_task_event_t; -typedef struct stru_task_msg_queue *stru_task_msg_queue_t; +/** 定时器回调函数类型 */ +typedef void (*timer_func_cb)(void *arg); + +/** 不透明句柄类型 */ +typedef void *stru_task_timer_t; +typedef void *stru_task_event_t; +typedef void *stru_task_msg_queue_t; /* ================================================================ - * Timer callback — returns 0 to continue, non-zero to stop + * 定时器标志 * ================================================================ */ -typedef int (*timer_func_cb)(void *arg); +/** 单次触发(到期后自动停止) */ +#define TASK_TIMER_FLAG_ONCE 0x01 -/* Timer flags */ -#define TIMER_ONCE 0 /* one-shot */ -#define TIMER_PERIOD 1 /* periodic */ +/** 周期触发(到期后自动重新计时) */ +#define TASK_TIMER_FLAG_PERIODIC 0x02 /* ================================================================ - * Timer API (SPEC T01-T07) + * 事件等待方式 + * ================================================================ */ + +/** 永久等待(不超时) */ +#define TASK_EVENT_WAIT_FOREVER 0xFFFFFFFF + +/** 事件标记:等待所有位都置位(AND 模式) */ +#define TASK_EVENT_FLAG_AND 0x01 + +/** 事件标记:等待任意位置位(OR 模式) */ +#define TASK_EVENT_FLAG_OR 0x02 + +/** 事件标记:接收后自动清除已匹配的位 */ +#define TASK_EVENT_FLAG_CLEAR 0x04 + +/* ================================================================ + * 通用延时 * ================================================================ */ /** - * @brief Create a timer (does not start automatically) - * @param name timer name for debugging - * @param cb callback function - * @param arg user argument passed to callback - * @param timeout_ms interval in milliseconds - * @param flags TIMER_ONCE or TIMER_PERIOD - * @return timer handle, NULL on failure + * @brief 任务延时(毫秒级阻塞等待) + * @param ms 延时毫秒数 */ -stru_task_timer_t task_timer_create(const char *name, timer_func_cb cb, - void *arg, uint32_t timeout_ms, int flags); - -/** Start the timer */ -int task_timer_start(stru_task_timer_t pt); - -/** Stop the timer */ -int task_timer_stop(stru_task_timer_t pt); - -/** Restart with new interval */ -int task_timer_restart(stru_task_timer_t pt, uint32_t timeout_ms); - -/** Destroy and free the timer */ -int task_timer_destroy(stru_task_timer_t pt); - -/** Check if timer is currently active */ -int task_timer_is_active(stru_task_timer_t pt); +void task_sleep_ms(uint32_t ms); /* ================================================================ - * Event API (SPEC T08-T13) + * 事件 API * ================================================================ */ -#define EVENT_OPT_AND 0 /* wait for ALL bits set */ -#define EVENT_OPT_OR 1 /* wait for ANY bit set */ - /** - * @brief Create an event object - * @param name event name for debugging - * @return event handle, NULL on failure + * @brief 创建事件对象 + * @param name 事件名称(调试用) + * @return 事件句柄,失败返回 NULL */ stru_task_event_t task_event_create(const char *name); -/** Destroy event object */ -int task_event_destroy(stru_task_event_t pe); - -/** Set (send) event bits */ -int task_event_send(stru_task_event_t pe, uint32_t bits); +/** + * @brief 销毁事件对象 + * @param p_event 事件句柄 + * @return 0 成功,-1 失败 + */ +int task_event_destroy(stru_task_event_t p_event); /** - * @brief Wait for event bits - * @param pe event handle - * @param set bits to wait for - * @param opt EVENT_OPT_AND or EVENT_OPT_OR - * @param timeout_ms timeout in ms (0 = forever) - * @param recved [out] bits actually received - * @return 0 on success, -1 on timeout + * @brief 发送事件(设置事件位) + * @param p_event 事件句柄 + * @param event 要设置的事件位掩码 + * @return 0 成功,-1 失败 */ -int task_event_recv(stru_task_event_t pe, uint32_t set, uint32_t opt, +int task_event_send(stru_task_event_t p_event, uint32_t event); + +/** + * @brief 等待事件 + * @param p_event 事件句柄 + * @param set 期望的事件位掩码 + * @param opt 等待选项(TASK_EVENT_FLAG_AND/OR/CLEAR 组合) + * @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待) + * @param recved 输出参数:实际收到的事件位 + * @return 0 成功,-1 超时或失败 + */ +int task_event_recv(stru_task_event_t p_event, uint32_t set, uint32_t opt, uint32_t timeout_ms, uint32_t *recved); -/** Clear specific event bits */ -int task_event_clear(stru_task_event_t pe, uint32_t bits); +/** + * @brief 清除事件位 + * @param p_event 事件句柄 + * @param event 要清除的事件位掩码 + * @return 0 成功,-1 失败 + */ +int task_event_clear(stru_task_event_t p_event, uint32_t event); -/** Query current event bits (non-blocking) */ -uint32_t task_event_query(stru_task_event_t pe); +/** + * @brief 查询当前事件位(非阻塞) + * @param p_event 事件句柄 + * @return 当前事件位掩码 + */ +uint32_t task_event_query(stru_task_event_t p_event); /* ================================================================ - * Message Queue API (SPEC T14-T21) + * 消息队列 API * ================================================================ */ /** - * @brief Create a fixed-size message queue - * @param name queue name - * @param msg_size max size of each message (bytes) - * @param msg_num max number of messages - * @return queue handle, NULL on failure + * @brief 创建定长消息队列 + * @param name 队列名称(调试用) + * @param msg_size 每条消息的最大字节数 + * @param msg_num 队列容量(最大消息条数) + * @return 队列句柄,失败返回 NULL */ stru_task_msg_queue_t task_msg_queue_create(const char *name, uint32_t msg_size, uint32_t msg_num); -/** Destroy message queue */ -int task_msg_queue_destroy(stru_task_msg_queue_t pq); +/** + * @brief 销毁消息队列 + * @param p_queue 队列句柄 + * @return 0 成功,-1 失败 + */ +int task_msg_queue_destroy(stru_task_msg_queue_t p_queue); -/** Send message (blocking if queue full) */ -int task_msg_queue_send(stru_task_msg_queue_t pq, const void *msg, uint32_t size); +/** + * @brief 发送消息(队列满时阻塞等待) + * @param p_queue 队列句柄 + * @param msg 消息内容指针 + * @param size 消息实际字节数(<= msg_size) + * @return 0 成功,-1 失败 + */ +int task_msg_queue_send(stru_task_msg_queue_t p_queue, const void *msg, + uint32_t size); -/** Send message with timeout (ms), returns -1 on timeout */ -int task_msg_queue_send_timeout(stru_task_msg_queue_t pq, const void *msg, +/** + * @brief 发送消息(带超时) + * @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待) + * @return 0 成功,-1 超时或失败 + */ +int task_msg_queue_send_timeout(stru_task_msg_queue_t p_queue, const void *msg, uint32_t size, uint32_t timeout_ms); -/** Receive message with timeout (ms), returns -1 on timeout */ -int task_msg_queue_recv(stru_task_msg_queue_t pq, void *msg, uint32_t size, - uint32_t timeout_ms); +/** + * @brief 接收消息(带超时) + * @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待) + * @return 0 成功,-1 超时或失败 + */ +int task_msg_queue_recv(stru_task_msg_queue_t p_queue, void *msg, + uint32_t size, uint32_t timeout_ms); -/** Try receive (non-blocking), returns 0 on success, -1 if empty */ -int task_msg_queue_try_recv(stru_task_msg_queue_t pq, void *msg, uint32_t size); +/** + * @brief 尝试接收消息(非阻塞,队列空立即返回 -1) + * @return 0 成功,-1 队列空 + */ +int task_msg_queue_try_recv(stru_task_msg_queue_t p_queue, void *msg, + uint32_t size); -/** Get number of messages currently in queue */ -uint32_t task_msg_queue_get_count(stru_task_msg_queue_t pq); +/** + * @brief 获取队列中当前消息数 + */ +uint32_t task_msg_queue_get_count(stru_task_msg_queue_t p_queue); -/** Get free space in queue */ -uint32_t task_msg_queue_space(stru_task_msg_queue_t pq); +/** + * @brief 获取队列剩余可用空间(条数) + */ +uint32_t task_msg_queue_space(stru_task_msg_queue_t p_queue); + +/* ================================================================ + * 定时器 API + * ================================================================ */ + +/** + * @brief 创建定时器(创建后不会自动启动,需调用 task_timer_start) + * @param name 定时器名称(调试用) + * @param fun_cb 到期回调函数 + * @param arg 回调参数 + * @param timeout_ms 定时周期(毫秒) + * @param flags 标志位(TASK_TIMER_FLAG_ONCE 或 TASK_TIMER_FLAG_PERIODIC) + * @return 定时器句柄,失败返回 NULL + */ +stru_task_timer_t task_timer_create(const char *name, timer_func_cb fun_cb, + void *arg, uint32_t timeout_ms, int flags); + +/** + * @brief 启动定时器 + * @return 0 成功,-1 失败 + */ +int task_timer_start(stru_task_timer_t p_timer); + +/** + * @brief 停止定时器 + * @return 0 成功,-1 失败 + */ +int task_timer_stop(stru_task_timer_t p_timer); + +/** + * @brief 重启定时器(可修改周期) + * @param timeout_ms 新的定时周期(毫秒) + * @return 0 成功,-1 失败 + */ +int task_timer_restart(stru_task_timer_t p_timer, uint32_t timeout_ms); + +/** + * @brief 销毁定时器 + * @return 0 成功,-1 失败 + */ +int task_timer_destroy(stru_task_timer_t p_timer); + +/** + * @brief 查询定时器是否在运行 + * @return 1=运行中,0=已停止 + */ +int task_timer_is_active(stru_task_timer_t p_timer); #ifdef __cplusplus } #endif -#endif + +#endif /* _MY_TASK_H_ */ diff --git a/release/src/public/libtask/makefile b/release/src/public/libtask/makefile index 6d098e9..81f320c 100644 --- a/release/src/public/libtask/makefile +++ b/release/src/public/libtask/makefile @@ -5,21 +5,28 @@ O := $(LIB_REL)/$(M).a S := $(SRC_ROOT_DIR)/$(L)/libtask/src I := -I$(SRC_ROOT_DIR)/$(L)/libtask/inc B := $(CURDIR)/$(M)/obj -SRCS := $(wildcard $(S)/*.cpp) -OBJS := $(patsubst $(S)/%.cpp,$(B)/%.o,$(SRCS)) -F := $(CXX_FLAGS) $(I) -I$(SRC_ROOT_DIR)/public/liblog/inc +SRCS := $(wildcard $(S)/*.c) +OBJS := $(patsubst $(S)/%.c, $(B)/%.o, $(SRCS)) +F := $(C_FLAGS) $(I) + +.PHONY: all all: @mkdir -p $(ROOT_DIR)/release/inc @cp -f $(S:src=inc)/*.h $(ROOT_DIR)/release/inc/ 2>/dev/null; true @$(MAKE) $(O) + $(O): $(OBJS) @mkdir -p $(dir $@) $(AR) rcs $@ $^ @echo "[$(M)] built" -$(B)/%.o: $(S)/%.cpp + +$(B)/%.o: $(S)/%.c @mkdir -p $(dir $@) - $(CXX) $(F) -c $< -o $@ + $(CC) $(F) -c $< -o $@ + +.PHONY: clean clean: rm -rf $(B) $(O) + +.PHONY: rebuild rebuild: clean all -.PHONY: all clean rebuild diff --git a/src/public/libfunc/src/myFunc.c b/src/public/libfunc/src/myFunc.c index 4a8017f..52fe113 100644 --- a/src/public/libfunc/src/myFunc.c +++ b/src/public/libfunc/src/myFunc.c @@ -17,7 +17,7 @@ #include #include -/* ==== 1. Checksum: CRC16/32 + ByteSum + FileCRC ==== */ +/* ==== 1. 校验计算:CRC16/CRC32/累加校验和/文件CRC ==== */ LOCAL const uint16_t _crc16_tab[256] = { 0x0000,0xc0c1,0xc181,0x0140,0xc301,0x03c0,0x0280,0xc241,0xc601,0x06c0,0x0780,0xc741,0x0500,0xc5c1,0xc481,0x0440, @@ -195,7 +195,7 @@ uint32_t func_cal_file_crc32(const char *path) return crc ^ 0xFFFFFFFF; } -/* ==== 2. String Convert ==== */ +/* ==== 2. 字符串转换 ==== */ uint8_t func_hex_ch(char c) { @@ -418,7 +418,7 @@ int func_str2argv(char *s, uint8_t *argc, char *argv[], uint8_t max) return 0; } -/* ==== 3. Time Process ==== */ +/* ==== 3. 时间处理 ==== */ /** * @brief stru_time_sys to formatted time string @@ -584,7 +584,7 @@ void func_time_cal2sys(stru_time_cal *src, stru_time_sys *dst) dst->ms = (uint16_t)(g->tm_sec * 1000 + src->usec / 1000); } -/* ==== 4. File & Directory ==== */ +/* ==== 4. 文件目录操作 ==== */ /** * @brief Check if directory exists @@ -853,7 +853,7 @@ int func_read_file_info(const char *p, stru_file_info *info, int check) return 0; } -/* ==== 5. Process Manager (Linux /proc) ==== */ +/* ==== 5. 进程管理(基于 Linux /proc) ==== */ /** * @brief Get current process name via /proc/self/comm @@ -1069,7 +1069,7 @@ int func_proc_self_dir(char *buf, uint32_t sz) return 0; } -/* ==== 6. Environment Paths ==== */ +/* ==== 6. 环境变量路径 ==== */ /** * @brief Get WORK_PATH env var @@ -1260,7 +1260,7 @@ int func_get_app_log(const char *a, char *b, uint32_t s) return _make_path("LOG_ROOT_PATH", a, NULL, b, s); } -/* ==== 7. IPC Message Queue (System V) ==== */ +/* ==== 7. IPC 消息队列(System V) ==== */ /** * @brief Create IPC message queue by process name diff --git a/src/public/liblist/inc/list.h b/src/public/liblist/inc/list.h index 20c6465..f5c03f3 100644 --- a/src/public/liblist/inc/list.h +++ b/src/public/liblist/inc/list.h @@ -1,9 +1,9 @@ /** * @file list.h - * @brief 内核风格侵入式双向循环链表(纯头文件,C/C++ 兼容) - * - * 用法:将 struct list_head 嵌入你的结构体,通过 list_entry 取回宿主指针。 - * 所有操作 O(1),遍历 O(n)。C++ 兼容:不用 new/class/typeof 等关键字。 + * @brief Linux 内核风格侵入式双向循环链表(纯头文件,C/C++ 兼容) + * @details 将 struct list_head 嵌入宿主结构体,通过 list_entry 取回宿主指针。 + * 所有操作 O(1),遍历 O(n)。 + * C++ 兼容:变量名不使用 new/class/typeof 等关键字。 */ #ifndef _LIST_H_ @@ -16,7 +16,7 @@ extern "C" { #endif -/* ---- 节点 ---- */ +/* ---- 链表节点 ---- */ struct list_head { struct list_head *next; @@ -27,13 +27,16 @@ struct list_head #define LIST_HEAD_INIT(n) { &(n), &(n) } #define LIST_HEAD(n) struct list_head n = LIST_HEAD_INIT(n) +/** + * @brief 运行时初始化链表头 + */ static inline void INIT_LIST_HEAD(struct list_head *h) { h->next = h; h->prev = h; } -/* ---- 内部:在 prev 和 next 之间插入 node ---- */ +/* ---- 内部辅助:在 prev 和 next 之间插入 node ---- */ static inline void __list_add(struct list_head *node, struct list_head *prev, struct list_head *next) @@ -44,7 +47,7 @@ static inline void __list_add(struct list_head *node, prev->next = node; } -/* ---- 内部:删除 prev 和 next 之间的节点 ---- */ +/* ---- 内部辅助:移除 prev 和 next 之间的节点 ---- */ static inline void __list_del(struct list_head *prev, struct list_head *next) { @@ -52,43 +55,54 @@ static inline void __list_del(struct list_head *prev, prev->next = next; } -/* ---- 添加 ---- */ +/* ---- 添加操作 ---- */ + +/** 头插法:插入到 head 之后(作为第一个元素) */ static inline void list_add(struct list_head *node, struct list_head *head) { __list_add(node, head, head->next); } +/** 尾插法:插入到 head 之前(作为最后一个元素) */ static inline void list_add_tail(struct list_head *node, struct list_head *head) { __list_add(node, head->prev, head); } -/* ---- 删除 ---- */ +/* ---- 删除操作 ---- */ + +/** 从链表移除节点(不释放内存) */ static inline void list_del(struct list_head *e) { __list_del(e->prev, e->next); } +/** 移除并重新初始化节点(安全删除,防止悬空指针) */ static inline void list_del_init(struct list_head *e) { __list_del(e->prev, e->next); INIT_LIST_HEAD(e); } -/* ---- 移动 ---- */ +/* ---- 移动操作 ---- */ + +/** 将节点移动到新链表头部 */ static inline void list_move(struct list_head *l, struct list_head *h) { __list_del(l->prev, l->next); list_add(l, h); } +/** 将节点移动到新链表尾部 */ static inline void list_move_tail(struct list_head *l, struct list_head *h) { __list_del(l->prev, l->next); list_add_tail(l, h); } -/* ---- 替换 ---- */ +/* ---- 替换操作 ---- */ + +/** 用 node 替换 old */ static inline void list_replace(struct list_head *old, struct list_head *node) { node->next = old->next; @@ -97,6 +111,7 @@ static inline void list_replace(struct list_head *old, struct list_head *node) node->prev->next = node; } +/** 替换后初始化被替换节点 */ static inline void list_replace_init(struct list_head *old, struct list_head *node) { @@ -104,43 +119,56 @@ static inline void list_replace_init(struct list_head *old, INIT_LIST_HEAD(old); } -/* ---- 判断 ---- */ +/* ---- 判断操作 ---- */ + +/** 判断链表是否为空 */ static inline int list_empty(const struct list_head *h) { return h->next == h; } +/** 判断节点是否已链入链表 */ static inline int list_is_linked(const struct list_head *e) { return e->next != e; } -/* ---- 宿主指针 ---- */ +/* ---- 节点 ↔ 宿主指针转换 ---- */ + +/** 从链表节点指针取回宿主结构体指针 */ #define list_entry(ptr, type, member) \ ((type *)((char *)(ptr) - offsetof(type, member))) +/** 获取第一个宿主元素 */ #define list_first_entry(h, type, member) \ list_entry((h)->next, type, member) +/** 获取最后一个宿主元素 */ #define list_last_entry(h, type, member) \ list_entry((h)->prev, type, member) +/** 安全获取第一个元素(链表空返回 NULL) */ #define list_first_entry_or_null(h, type, member) \ (list_empty(h) ? NULL : list_first_entry(h, type, member)) -/* ---- 遍历 ---- */ +/* ---- 遍历操作 ---- */ + +/** 遍历链表节点(仅获取 struct list_head 指针) */ #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) +/** 安全遍历节点(可在遍历中删除 pos) */ #define list_for_each_safe(pos, n, head) \ for (pos = (head)->next, n = pos->next; pos != (head); \ pos = n, n = pos->next) +/** 遍历宿主元素 */ #define list_for_each_entry(pos, head, member) \ for (pos = list_first_entry(head, __typeof__(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, __typeof__(*pos), member)) +/** 安全遍历宿主元素(可在遍历中删除 pos) */ #define list_for_each_entry_safe(pos, n, head, member) \ for (pos = list_first_entry(head, __typeof__(*pos), member), \ n = list_entry(pos->member.next, __typeof__(*pos), member); \ @@ -148,7 +176,9 @@ static inline int list_is_linked(const struct list_head *e) pos = n, \ n = list_entry(n->member.next, __typeof__(*n), member)) -/* ---- 拼接 ---- */ +/* ---- 拼接操作 ---- */ + +/** 将 src 链表拼接到 dst 头部,src 被清空 */ static inline void list_splice_init(struct list_head *src, struct list_head *dst) { @@ -169,4 +199,5 @@ static inline void list_splice_init(struct list_head *src, #ifdef __cplusplus } #endif -#endif + +#endif /* _LIST_H_ */ diff --git a/src/public/liblog/inc/myLog.h b/src/public/liblog/inc/myLog.h index c6aabdc..1d6f5e8 100644 --- a/src/public/liblog/inc/myLog.h +++ b/src/public/liblog/inc/myLog.h @@ -1,9 +1,9 @@ /** * @file myLog.h * @brief 异步日志系统接口(纯 C) - * @details 提供 INFO/ERROR 两级异步日志,非阻塞写入。 - * 支持控制台彩色输出、文件输出、文件按大小轮转。 - * 首次调用 log_prt 时自动初始化,无需手动 init。 + * @details 支持 INFO/ERROR 两级日志,非阻塞写入。 + * 首次调用 log_prt 时自动初始化(pthread_once 懒启动),无需手动 init。 + * 控制台支持彩色 ANSI 输出,文件支持按大小自动轮转。 */ #ifndef _MY_LOG_H_ @@ -14,25 +14,26 @@ extern "C" { #endif -/** 日志级别:INFO(普通信息) */ +/** 日志级别:INFO(普通信息,白色输出) */ #define LOG_INFO 0 -/** 日志级别:ERROR(错误信息,控制台红色输出) */ + +/** 日志级别:ERROR(错误信息,红色输出) */ #define LOG_ERROR 1 /** - * @brief 手动初始化日志系统(可选,log_prt 自动懒初始化) - * @param dir 日志文件目录路径,传 NULL 则默认 /tmp/logs + * @brief 手动初始化日志系统(可选,首次 log_prt 会自动触发) + * @param dir 日志文件目录路径,传 NULL 则使用默认 /tmp/logs * @return 0 成功 */ int log_init(const char *dir); /** * @brief 核心日志打印函数(非阻塞,消息入队列后立即返回) - * @param level 日志级别 LOG_INFO 或 LOG_ERROR - * @param file 源文件名(通常传 __FILE__) - * @param func 函数名(通常传 __FUNCTION__) - * @param line 行号(通常传 __LINE__) - * @param fmt printf 风格格式化字符串 + * @param level 日志级别(LOG_INFO 或 LOG_ERROR) + * @param file 源文件名(通常传 __FILE__) + * @param func 函数名(通常传 __FUNCTION__) + * @param line 行号(通常传 __LINE__) + * @param fmt printf 格式化字符串 * @param ... 可变参数 */ void log_prt(uint32_t level, const char *file, const char *func, @@ -53,13 +54,13 @@ void log_console_off(void); /** 等待异步队列清空(阻塞直到所有消息写入完成) */ void log_flush(void); -/** 停止工作线程、关闭文件、释放消息池内存 */ +/** 停止工作线程、关闭文件、释放消息池 */ void log_cleanup(void); -/** INFO 级别日志宏 */ +/** INFO 级别便捷日志宏 */ #define LOG_I(fmt, ...) log_prt(LOG_INFO, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) -/** ERROR 级别日志宏 */ +/** ERROR 级别便捷日志宏 */ #define LOG_E(fmt, ...) log_prt(LOG_ERROR, __FILE__, __FUNCTION__, __LINE__, fmt, ##__VA_ARGS__) #ifdef __cplusplus diff --git a/src/public/libmd5/inc/myMd5.h b/src/public/libmd5/inc/myMd5.h index f2b547e..0b5f9a2 100644 --- a/src/public/libmd5/inc/myMd5.h +++ b/src/public/libmd5/inc/myMd5.h @@ -1,7 +1,8 @@ /** * @file myMd5.h - * @brief MD5 message digest (RFC 1321) - * @details Computes 128-bit hash. Supports streaming update. + * @brief MD5 消息摘要算法接口(RFC 1321) + * @details 计算 128 位哈希值,支持流式输入。 + * 提供单次调用便捷函数 md5_string()。 */ #ifndef _MY_MD5_H_ @@ -14,25 +15,41 @@ extern "C" #endif /** - * @brief MD5 context (state + count + pending buffer) + * @brief MD5 计算上下文(状态 + 计数 + 待处理缓冲区) */ typedef struct { - uint32_t state[4]; /* A, B, C, D */ - uint32_t count[2]; /* bit count low/high */ - unsigned char buf[64]; /* pending bytes */ + uint32_t state[4]; /* A, B, C, D 四个 32 位状态寄存器 */ + uint32_t count[2]; /* 位计数(低 32 位, 高 32 位) */ + unsigned char buf[64]; /* 待处理数据缓冲区(64 字节) */ } stru_md5_ctx; -/** Initialize context with magic constants */ +/** + * @brief 初始化 MD5 上下文 + * @param ctx 上下文指针(设置魔数 A=0x67452301 B=0xefcdab89 C=0x98badcfe D=0x10325476) + */ void md5_start(stru_md5_ctx *ctx); -/** Feed data, callable multiple times */ +/** + * @brief 输入待计算数据(可多次调用,支持流式处理) + * @param ctx 上下文指针 + * @param data 数据缓冲区 + * @param len 数据长度(字节) + */ void md5_update(stru_md5_ctx *ctx, const unsigned char *data, int len); -/** Finalize, get 16-byte digest */ +/** + * @brief 完成计算,输出 16 字节 MD5 摘要 + * @param ctx 上下文指针 + * @param result 输出缓冲区(至少 16 字节) + */ void md5_final(stru_md5_ctx *ctx, unsigned char result[16]); -/** One-shot: compute MD5 of string, output 32-char hex (uppercase) */ +/** + * @brief 单次调用便捷函数:计算字符串的 MD5,返回大写十六进制字符串 + * @param input 输入字符串(以 '\0' 结尾) + * @param output 输出缓冲区(至少 33 字节,含结尾 '\0') + */ void md5_string(const char *input, char output[33]); #ifdef __cplusplus diff --git a/src/public/libmd5/src/myMd5.c b/src/public/libmd5/src/myMd5.c index e4e4571..2c3c234 100644 --- a/src/public/libmd5/src/myMd5.c +++ b/src/public/libmd5/src/myMd5.c @@ -1,6 +1,8 @@ /** * @file myMd5.c - * @brief MD5 implementation (RFC 1321, 16 steps x 4 rounds) + * @brief MD5 消息摘要算法实现(RFC 1321) + * @details 4 轮 × 16 步变换,自主编写。 + * 处理流程:填充原始消息 → 64 字节分块处理 → 输出 16 字节摘要。 */ #include "myMd5.h" @@ -8,13 +10,23 @@ #include #include +/* ================================================================ + * MD5 核心原语(RFC 1321 §3.4) + * ================================================================ */ + +/** 四个非线性函数 */ #define F(x, y, z) (((x) & (y)) | ((~x) & (z))) #define G(x, y, z) (((x) & (z)) | ((y) & (~z))) #define H(x, y, z) ((x) ^ (y) ^ (z)) #define I(x, y, z) ((y) ^ ((x) | (~z))) +/** 循环左移 */ #define ROTL(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +/** + * @brief 单步变换宏 + * @detail a = b + ROTL(a + f(b,c,d) + x + ac, s) + */ #define STEP(f, a, b, c, d, x, s, ac) \ do \ { \ @@ -23,6 +35,9 @@ (a) += (b); \ } while (0) +/** + * @brief 小端解码:字节数组 → uint32 数组 + */ LOCAL void md5_decode(uint32_t *out, const unsigned char *in, int n) { for (int i = 0, j = 0; j < n; i++, j += 4) @@ -34,6 +49,9 @@ LOCAL void md5_decode(uint32_t *out, const unsigned char *in, int n) } } +/** + * @brief 小端编码:uint32 数组 → 字节数组 + */ LOCAL void md5_encode(unsigned char *out, const uint32_t *in, int n) { for (int i = 0, j = 0; j < n; i++, j += 4) @@ -45,14 +63,19 @@ LOCAL void md5_encode(unsigned char *out, const uint32_t *in, int n) } } +/** + * @brief MD5 核心变换:处理一个 64 字节块 + * @detail 4 轮 × 16 步 = 64 步操作,每步使用不同的非线性函数 + */ LOCAL void md5_transform(uint32_t state[4], const unsigned char block[64]) { uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; uint32_t x[16]; + /* 将 64 字节块解码为 16 个 uint32 */ md5_decode(x, block, 64); - /* Round 1 */ + /* 第 1 轮:FF */ STEP(F, a, b, c, d, x[ 0], 7, 0xd76aa478); STEP(F, d, a, b, c, x[ 1], 12, 0xe8c7b756); STEP(F, c, d, a, b, x[ 2], 17, 0x242070db); @@ -70,7 +93,7 @@ LOCAL void md5_transform(uint32_t state[4], const unsigned char block[64]) STEP(F, c, d, a, b, x[14], 17, 0xa679438e); STEP(F, b, c, d, a, x[15], 22, 0x49b40821); - /* Round 2 */ + /* 第 2 轮:GG */ STEP(G, a, b, c, d, x[ 1], 5, 0xf61e2562); STEP(G, d, a, b, c, x[ 6], 9, 0xc040b340); STEP(G, c, d, a, b, x[11], 14, 0x265e5a51); @@ -88,7 +111,7 @@ LOCAL void md5_transform(uint32_t state[4], const unsigned char block[64]) STEP(G, c, d, a, b, x[ 7], 14, 0x676f02d9); STEP(G, b, c, d, a, x[12], 20, 0x8d2a4c8a); - /* Round 3 */ + /* 第 3 轮:HH */ STEP(H, a, b, c, d, x[ 5], 4, 0xfffa3942); STEP(H, d, a, b, c, x[ 8], 11, 0x8771f681); STEP(H, c, d, a, b, x[11], 16, 0x6d9d6122); @@ -106,7 +129,7 @@ LOCAL void md5_transform(uint32_t state[4], const unsigned char block[64]) STEP(H, c, d, a, b, x[15], 16, 0x1fa27cf8); STEP(H, b, c, d, a, x[ 2], 23, 0xc4ac5665); - /* Round 4 */ + /* 第 4 轮:II */ STEP(I, a, b, c, d, x[ 0], 6, 0xf4292244); STEP(I, d, a, b, c, x[ 7], 10, 0x432aff97); STEP(I, c, d, a, b, x[14], 15, 0xab9423a7); @@ -124,48 +147,75 @@ LOCAL void md5_transform(uint32_t state[4], const unsigned char block[64]) STEP(I, c, d, a, b, x[ 2], 15, 0x2ad7d2bb); STEP(I, b, c, d, a, x[ 9], 21, 0xeb86d391); + /* 累加回状态寄存器 */ state[0] += a; state[1] += b; state[2] += c; state[3] += d; + /* 清零敏感数据,防止泄漏 */ memset(x, 0, sizeof(x)); } +/* ================================================================ + * 公开 API + * ================================================================ */ + +/** + * @brief 初始化 MD5 上下文,设置标准魔数值 + */ void md5_start(stru_md5_ctx *ctx) { - if (!ctx) { return; } + if (!ctx) + { + return; + } ctx->count[0] = 0; ctx->count[1] = 0; + + /* RFC 1321 标准魔数 */ ctx->state[0] = 0x67452301; ctx->state[1] = 0xefcdab89; ctx->state[2] = 0x98badcfe; ctx->state[3] = 0x10325476; + memset(ctx->buf, 0, sizeof(ctx->buf)); } +/** + * @brief 输入数据(支持分多次调用) + * @detail 先填满内部 64 字节缓冲区,再按 512 位块进行变换。 + */ void md5_update(stru_md5_ctx *ctx, const unsigned char *data, int len) { - if (!ctx || !data || len <= 0) { return; } + if (!ctx || !data || len <= 0) + { + return; + } + /* 当前缓冲区偏移 */ unsigned idx = (unsigned)((ctx->count[0] >> 3) & 0x3F); unsigned ilen = (unsigned)len; + /* 更新位计数(低 32 + 高 32) */ if ((ctx->count[0] += ((uint32_t)ilen << 3)) < ((uint32_t)ilen << 3)) { ctx->count[1]++; } + ctx->count[1] += (uint32_t)(ilen >> 29); unsigned avail = 64 - idx; unsigned i = 0; + /* 如果输入足够填满剩余缓冲空间 */ if (ilen >= avail) { memcpy(&ctx->buf[idx], data, avail); md5_transform(ctx->state, ctx->buf); + /* 处理完整 64 字节块 */ for (i = avail; i + 63 < ilen; i += 64) { md5_transform(ctx->state, &data[i]); @@ -174,33 +224,54 @@ void md5_update(stru_md5_ctx *ctx, const unsigned char *data, int len) idx = 0; } + /* 剩余不足一块的数据暂存缓冲区 */ memcpy(&ctx->buf[idx], &data[i], ilen - i); } +/** + * @brief 完成计算,输出 16 字节 MD5 摘要 + * @detail 填充 0x80 + 零 + 8 字节位计数 → 最终变换 → 小端输出 + */ void md5_final(stru_md5_ctx *ctx, unsigned char result[16]) { - if (!ctx || !result) { return; } + if (!ctx || !result) + { + return; + } unsigned char bits[8]; + /* 保存位计数(小端 8 字节) */ md5_encode(bits, ctx->count, 8); + /* 计算填充字节数(总填充后长度 = 56 mod 64) */ unsigned idx = (unsigned)((ctx->count[0] >> 3) & 0x3F); unsigned pad = (idx < 56) ? (56 - idx) : (120 - idx); static unsigned char padding[64] = { 0x80, 0 }; + /* 先填充分隔符 + 零,再追加位计数 */ md5_update(ctx, padding, (int)pad); md5_update(ctx, bits, 8); + + /* 输出 16 字节摘要(小端) */ md5_encode(result, ctx->state, 16); + + /* 清零上下文(安全清理) */ memset(ctx, 0, sizeof(*ctx)); } +/** + * @brief 单次调用:计算字符串的 MD5 并返回大写十六进制字符串 + */ void md5_string(const char *input, char output[33]) { - if (!input || !output) { return; } + if (!input || !output) + { + return; + } - stru_md5_ctx ctx; + stru_md5_ctx ctx; unsigned char digest[16]; md5_start(&ctx); @@ -213,5 +284,8 @@ void md5_string(const char *input, char output[33]) } output[32] = '\0'; + + /* 清理敏感数据 */ + memset(&ctx, 0, sizeof(ctx)); memset(digest, 0, sizeof(digest)); } diff --git a/src/public/libtask/inc/myTask.h b/src/public/libtask/inc/myTask.h index 0cfacaf..fc093b0 100644 --- a/src/public/libtask/inc/myTask.h +++ b/src/public/libtask/inc/myTask.h @@ -1,11 +1,15 @@ /** * @file myTask.h - * @brief Task framework: timers + events + message queues (C interface) - * @details Based on SPEC §8 analysis. Uses C++ internally. + * @brief 任务框架接口 — 定时器 + 事件 + 消息队列(C 接口) + * @details 基于 SPEC §8 原工程分析。 + * 定时器基于 timerfd + epoll 实现,精确到毫秒。 + * 事件基于位图 + pthread 条件变量实现。 + * 消息队列基于环形缓冲区 + 互斥锁 + 条件变量实现。 */ #ifndef _MY_TASK_H_ #define _MY_TASK_H_ + #include #ifdef __cplusplus @@ -14,130 +18,219 @@ extern "C" #endif /* ================================================================ - * Opaque handles + * 通用定义 * ================================================================ */ -typedef struct stru_task_timer *stru_task_timer_t; -typedef struct stru_task_event *stru_task_event_t; -typedef struct stru_task_msg_queue *stru_task_msg_queue_t; +/** 定时器回调函数类型 */ +typedef void (*timer_func_cb)(void *arg); + +/** 不透明句柄类型 */ +typedef void *stru_task_timer_t; +typedef void *stru_task_event_t; +typedef void *stru_task_msg_queue_t; /* ================================================================ - * Timer callback — returns 0 to continue, non-zero to stop + * 定时器标志 * ================================================================ */ -typedef int (*timer_func_cb)(void *arg); +/** 单次触发(到期后自动停止) */ +#define TASK_TIMER_FLAG_ONCE 0x01 -/* Timer flags */ -#define TIMER_ONCE 0 /* one-shot */ -#define TIMER_PERIOD 1 /* periodic */ +/** 周期触发(到期后自动重新计时) */ +#define TASK_TIMER_FLAG_PERIODIC 0x02 /* ================================================================ - * Timer API (SPEC T01-T07) + * 事件等待方式 + * ================================================================ */ + +/** 永久等待(不超时) */ +#define TASK_EVENT_WAIT_FOREVER 0xFFFFFFFF + +/** 事件标记:等待所有位都置位(AND 模式) */ +#define TASK_EVENT_FLAG_AND 0x01 + +/** 事件标记:等待任意位置位(OR 模式) */ +#define TASK_EVENT_FLAG_OR 0x02 + +/** 事件标记:接收后自动清除已匹配的位 */ +#define TASK_EVENT_FLAG_CLEAR 0x04 + +/* ================================================================ + * 通用延时 * ================================================================ */ /** - * @brief Create a timer (does not start automatically) - * @param name timer name for debugging - * @param cb callback function - * @param arg user argument passed to callback - * @param timeout_ms interval in milliseconds - * @param flags TIMER_ONCE or TIMER_PERIOD - * @return timer handle, NULL on failure + * @brief 任务延时(毫秒级阻塞等待) + * @param ms 延时毫秒数 */ -stru_task_timer_t task_timer_create(const char *name, timer_func_cb cb, - void *arg, uint32_t timeout_ms, int flags); - -/** Start the timer */ -int task_timer_start(stru_task_timer_t pt); - -/** Stop the timer */ -int task_timer_stop(stru_task_timer_t pt); - -/** Restart with new interval */ -int task_timer_restart(stru_task_timer_t pt, uint32_t timeout_ms); - -/** Destroy and free the timer */ -int task_timer_destroy(stru_task_timer_t pt); - -/** Check if timer is currently active */ -int task_timer_is_active(stru_task_timer_t pt); +void task_sleep_ms(uint32_t ms); /* ================================================================ - * Event API (SPEC T08-T13) + * 事件 API * ================================================================ */ -#define EVENT_OPT_AND 0 /* wait for ALL bits set */ -#define EVENT_OPT_OR 1 /* wait for ANY bit set */ - /** - * @brief Create an event object - * @param name event name for debugging - * @return event handle, NULL on failure + * @brief 创建事件对象 + * @param name 事件名称(调试用) + * @return 事件句柄,失败返回 NULL */ stru_task_event_t task_event_create(const char *name); -/** Destroy event object */ -int task_event_destroy(stru_task_event_t pe); - -/** Set (send) event bits */ -int task_event_send(stru_task_event_t pe, uint32_t bits); +/** + * @brief 销毁事件对象 + * @param p_event 事件句柄 + * @return 0 成功,-1 失败 + */ +int task_event_destroy(stru_task_event_t p_event); /** - * @brief Wait for event bits - * @param pe event handle - * @param set bits to wait for - * @param opt EVENT_OPT_AND or EVENT_OPT_OR - * @param timeout_ms timeout in ms (0 = forever) - * @param recved [out] bits actually received - * @return 0 on success, -1 on timeout + * @brief 发送事件(设置事件位) + * @param p_event 事件句柄 + * @param event 要设置的事件位掩码 + * @return 0 成功,-1 失败 */ -int task_event_recv(stru_task_event_t pe, uint32_t set, uint32_t opt, +int task_event_send(stru_task_event_t p_event, uint32_t event); + +/** + * @brief 等待事件 + * @param p_event 事件句柄 + * @param set 期望的事件位掩码 + * @param opt 等待选项(TASK_EVENT_FLAG_AND/OR/CLEAR 组合) + * @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待) + * @param recved 输出参数:实际收到的事件位 + * @return 0 成功,-1 超时或失败 + */ +int task_event_recv(stru_task_event_t p_event, uint32_t set, uint32_t opt, uint32_t timeout_ms, uint32_t *recved); -/** Clear specific event bits */ -int task_event_clear(stru_task_event_t pe, uint32_t bits); +/** + * @brief 清除事件位 + * @param p_event 事件句柄 + * @param event 要清除的事件位掩码 + * @return 0 成功,-1 失败 + */ +int task_event_clear(stru_task_event_t p_event, uint32_t event); -/** Query current event bits (non-blocking) */ -uint32_t task_event_query(stru_task_event_t pe); +/** + * @brief 查询当前事件位(非阻塞) + * @param p_event 事件句柄 + * @return 当前事件位掩码 + */ +uint32_t task_event_query(stru_task_event_t p_event); /* ================================================================ - * Message Queue API (SPEC T14-T21) + * 消息队列 API * ================================================================ */ /** - * @brief Create a fixed-size message queue - * @param name queue name - * @param msg_size max size of each message (bytes) - * @param msg_num max number of messages - * @return queue handle, NULL on failure + * @brief 创建定长消息队列 + * @param name 队列名称(调试用) + * @param msg_size 每条消息的最大字节数 + * @param msg_num 队列容量(最大消息条数) + * @return 队列句柄,失败返回 NULL */ stru_task_msg_queue_t task_msg_queue_create(const char *name, uint32_t msg_size, uint32_t msg_num); -/** Destroy message queue */ -int task_msg_queue_destroy(stru_task_msg_queue_t pq); +/** + * @brief 销毁消息队列 + * @param p_queue 队列句柄 + * @return 0 成功,-1 失败 + */ +int task_msg_queue_destroy(stru_task_msg_queue_t p_queue); -/** Send message (blocking if queue full) */ -int task_msg_queue_send(stru_task_msg_queue_t pq, const void *msg, uint32_t size); +/** + * @brief 发送消息(队列满时阻塞等待) + * @param p_queue 队列句柄 + * @param msg 消息内容指针 + * @param size 消息实际字节数(<= msg_size) + * @return 0 成功,-1 失败 + */ +int task_msg_queue_send(stru_task_msg_queue_t p_queue, const void *msg, + uint32_t size); -/** Send message with timeout (ms), returns -1 on timeout */ -int task_msg_queue_send_timeout(stru_task_msg_queue_t pq, const void *msg, +/** + * @brief 发送消息(带超时) + * @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待) + * @return 0 成功,-1 超时或失败 + */ +int task_msg_queue_send_timeout(stru_task_msg_queue_t p_queue, const void *msg, uint32_t size, uint32_t timeout_ms); -/** Receive message with timeout (ms), returns -1 on timeout */ -int task_msg_queue_recv(stru_task_msg_queue_t pq, void *msg, uint32_t size, - uint32_t timeout_ms); +/** + * @brief 接收消息(带超时) + * @param timeout_ms 超时时间(毫秒,TASK_EVENT_WAIT_FOREVER=永久等待) + * @return 0 成功,-1 超时或失败 + */ +int task_msg_queue_recv(stru_task_msg_queue_t p_queue, void *msg, + uint32_t size, uint32_t timeout_ms); -/** Try receive (non-blocking), returns 0 on success, -1 if empty */ -int task_msg_queue_try_recv(stru_task_msg_queue_t pq, void *msg, uint32_t size); +/** + * @brief 尝试接收消息(非阻塞,队列空立即返回 -1) + * @return 0 成功,-1 队列空 + */ +int task_msg_queue_try_recv(stru_task_msg_queue_t p_queue, void *msg, + uint32_t size); -/** Get number of messages currently in queue */ -uint32_t task_msg_queue_get_count(stru_task_msg_queue_t pq); +/** + * @brief 获取队列中当前消息数 + */ +uint32_t task_msg_queue_get_count(stru_task_msg_queue_t p_queue); -/** Get free space in queue */ -uint32_t task_msg_queue_space(stru_task_msg_queue_t pq); +/** + * @brief 获取队列剩余可用空间(条数) + */ +uint32_t task_msg_queue_space(stru_task_msg_queue_t p_queue); + +/* ================================================================ + * 定时器 API + * ================================================================ */ + +/** + * @brief 创建定时器(创建后不会自动启动,需调用 task_timer_start) + * @param name 定时器名称(调试用) + * @param fun_cb 到期回调函数 + * @param arg 回调参数 + * @param timeout_ms 定时周期(毫秒) + * @param flags 标志位(TASK_TIMER_FLAG_ONCE 或 TASK_TIMER_FLAG_PERIODIC) + * @return 定时器句柄,失败返回 NULL + */ +stru_task_timer_t task_timer_create(const char *name, timer_func_cb fun_cb, + void *arg, uint32_t timeout_ms, int flags); + +/** + * @brief 启动定时器 + * @return 0 成功,-1 失败 + */ +int task_timer_start(stru_task_timer_t p_timer); + +/** + * @brief 停止定时器 + * @return 0 成功,-1 失败 + */ +int task_timer_stop(stru_task_timer_t p_timer); + +/** + * @brief 重启定时器(可修改周期) + * @param timeout_ms 新的定时周期(毫秒) + * @return 0 成功,-1 失败 + */ +int task_timer_restart(stru_task_timer_t p_timer, uint32_t timeout_ms); + +/** + * @brief 销毁定时器 + * @return 0 成功,-1 失败 + */ +int task_timer_destroy(stru_task_timer_t p_timer); + +/** + * @brief 查询定时器是否在运行 + * @return 1=运行中,0=已停止 + */ +int task_timer_is_active(stru_task_timer_t p_timer); #ifdef __cplusplus } #endif -#endif + +#endif /* _MY_TASK_H_ */ diff --git a/src/public/libtask/src/myTask.c b/src/public/libtask/src/myTask.c new file mode 100644 index 0000000..a42f4bf --- /dev/null +++ b/src/public/libtask/src/myTask.c @@ -0,0 +1,1037 @@ +/** + * @file myTask.c + * @brief 任务框架实现 — 定时器 + 事件 + 消息队列(纯 C) + * @details 基于 SPEC §8 原工程分析,从零自主编写。 + * 定时器基于 timerfd + epoll 精确到毫秒。 + * 事件基于位图 + pthread 条件变量。 + * 消息队列基于环形缓冲区,消息带长度前缀。 + */ + +#include "myTask.h" +#include "myBase.h" +#include "myLog.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ================================================================ + * 内部数据结构 + * ================================================================ */ + +/** + * @brief 事件对象(位图 + 条件变量 + 引用计数) + */ +typedef struct +{ + char name[64]; /* 事件名称(调试用) */ + uint32_t bits; /* 当前事件位掩码 */ + pthread_mutex_t lock; /* 互斥锁 */ + pthread_cond_t cond; /* 条件变量 */ + int ref_count; /* 引用计数(安全析构) */ +} stru_task_event; + +/** + * @brief 消息队列对象(环形缓冲区) + */ +typedef struct +{ + char name[64]; /* 队列名称(调试用) */ + uint8_t *buf; /* 环形缓冲区基址 */ + uint32_t msg_size; /* 单条消息最大字节数 */ + uint32_t max_msgs; /* 最大消息条数 */ + uint32_t msg_count; /* 当前消息数 */ + uint32_t head; /* 读位置 */ + uint32_t tail; /* 写位置 */ + pthread_mutex_t lock; /* 互斥锁 */ + pthread_cond_t cond; /* 条件变量 */ + int ref_count; /* 引用计数(安全析构) */ +} stru_task_msg_queue; + +/** + * @brief 定时器对象(基于 timerfd + epoll) + */ +typedef struct +{ + char name[64]; /* 定时器名称(调试用) */ + int timerfd; /* timerfd 文件描述符 */ + timer_func_cb cb; /* 到期回调函数 */ + void *arg; /* 回调参数 */ + uint32_t timeout_ms; /* 定时周期(毫秒) */ + int flags; /* ONCE / PERIODIC */ + int active; /* 是否已启动 */ + int running; /* 是否在 epoll 监听中 */ + pthread_mutex_t lock; /* 互斥锁 */ + int ref_count; /* 引用计数(安全析构) */ +} stru_task_timer; + +/* ================================================================ + * 全局定时器管理器(epoll + 独立线程) + * ================================================================ */ + +LOCAL int g_timer_epfd = -1; /* epoll 实例 fd */ +LOCAL int g_timer_evtfd = -1; /* eventfd(用于唤醒 epoll) */ +LOCAL pthread_t g_timer_thread; /* 定时器管理线程 */ +LOCAL pthread_mutex_t g_timer_lock = PTHREAD_MUTEX_INITIALIZER; +LOCAL int g_timer_inited = 0; + +/******************************************************************************* + * 定时器管理线程 + * @details 使用 epoll 统一监听所有定时器的 timerfd。 + * 通过 eventfd 实现安全唤醒,支持动态增删定时器。 + ******************************************************************************/ + +LOCAL void *timer_manager_thread(void *arg) +{ + (void)arg; + + struct epoll_event ev; + struct epoll_event events[64]; + + /* 创建 epoll 实例 */ + g_timer_epfd = epoll_create1(0); + + if (g_timer_epfd < 0) + { + LOG_E("epoll_create1 failed"); + + return NULL; + } + + /* 创建 eventfd 用于唤醒 */ + g_timer_evtfd = eventfd(0, EFD_NONBLOCK); + + if (g_timer_evtfd < 0) + { + LOG_E("eventfd failed"); + close(g_timer_epfd); + + return NULL; + } + + /* 将 eventfd 加入 epoll */ + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = NULL; + + if (epoll_ctl(g_timer_epfd, EPOLL_CTL_ADD, g_timer_evtfd, &ev) != 0) + { + LOG_E("epoll_ctl ADD eventfd failed"); + close(g_timer_evtfd); + close(g_timer_epfd); + + return NULL; + } + + /* 事件循环 */ + while (1) + { + int n = epoll_wait(g_timer_epfd, events, 64, -1); + + if (n < 0) + { + if (errno == EINTR) + { + continue; + } + + break; + } + + /* 遍历就绪事件 */ + for (int i = 0; i < n; i++) + { + if (events[i].data.ptr == NULL) + { + /* eventfd 唤醒:读取并丢弃 */ + uint64_t dummy; + + read(g_timer_evtfd, &dummy, sizeof(dummy)); + + continue; + } + + /* 定时器到期 */ + stru_task_timer *p = (stru_task_timer *)events[i].data.ptr; + uint64_t exp; + + read(p->timerfd, &exp, sizeof(exp)); + + /* 加锁后回调(避免竞态) */ + pthread_mutex_lock(&p->lock); + + if (p->active && p->cb) + { + p->cb(p->arg); + + /* 单次触发则自动停止 */ + if (p->flags & TASK_TIMER_FLAG_ONCE) + { + p->active = 0; + p->running = 0; + } + } + + pthread_mutex_unlock(&p->lock); + } + } + + /* 清理 epoll 资源 */ + close(g_timer_evtfd); + close(g_timer_epfd); + + return NULL; +} + +/** + * @brief 线程安全初始化定时器管理器 + * @details 首次调用时启动 epoll 线程 + */ +LOCAL void timer_manager_ensure(void) +{ + pthread_mutex_lock(&g_timer_lock); + + if (!g_timer_inited) + { + g_timer_inited = 1; + pthread_create(&g_timer_thread, NULL, timer_manager_thread, NULL); + } + + pthread_mutex_unlock(&g_timer_lock); +} + +/******************************************************************************* + * 通用延时函数 + ******************************************************************************/ + +/** + * @brief 毫秒级精度延时(使用 nanosleep) + */ +void task_sleep_ms(uint32_t ms) +{ + struct timespec req; + + req.tv_sec = ms / 1000; + req.tv_nsec = (ms % 1000) * 1000000; + + nanosleep(&req, NULL); +} + +/******************************************************************************* + * 事件子系统的公开 API 实现 + ******************************************************************************/ + +/** + * @brief 创建事件对象 + */ +stru_task_event_t task_event_create(const char *name) +{ + if (!name) + { + LOG_E("task_event_create: name is NULL"); + + return NULL; + } + + stru_task_event *p = (stru_task_event *)calloc(1, sizeof(stru_task_event)); + + if (!p) + { + LOG_E("task_event_create: malloc failed"); + + return NULL; + } + + strncpy(p->name, name, sizeof(p->name) - 1); + p->bits = 0; + p->ref_count = 1; + + pthread_mutex_init(&p->lock, NULL); + pthread_cond_init(&p->cond, NULL); + + return (stru_task_event_t)p; +} + +/** + * @brief 销毁事件对象(带引用计数保护) + */ +int task_event_destroy(stru_task_event_t p_event) +{ + if (!p_event) + { + LOG_E("task_event_destroy: p_event is NULL"); + + return -1; + } + + stru_task_event *p = (stru_task_event *)p_event; + + pthread_mutex_lock(&p->lock); + + p->ref_count--; + + if (p->ref_count > 0) + { + pthread_mutex_unlock(&p->lock); + + return 0; + } + + pthread_mutex_unlock(&p->lock); + pthread_mutex_destroy(&p->lock); + pthread_cond_destroy(&p->cond); + + free(p); + + return 0; +} + +/** + * @brief 发送事件(置位 + 广播唤醒) + */ +int task_event_send(stru_task_event_t p_event, uint32_t event) +{ + if (!p_event) + { + LOG_E("task_event_send: p_event is NULL"); + + return -1; + } + + stru_task_event *p = (stru_task_event *)p_event; + + pthread_mutex_lock(&p->lock); + p->bits |= event; + pthread_cond_broadcast(&p->cond); + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 等待事件(支持 AND/OR/CLEAR 三种模式) + */ +int task_event_recv(stru_task_event_t p_event, uint32_t set, uint32_t opt, + uint32_t timeout_ms, uint32_t *recved) +{ + if (!p_event) + { + LOG_E("task_event_recv: p_event is NULL"); + + return -1; + } + + stru_task_event *p = (stru_task_event *)p_event; + uint32_t matched; + int ret = 0; + struct timespec ts; + + pthread_mutex_lock(&p->lock); + + /* 计算超时绝对时间 */ + if (timeout_ms != TASK_EVENT_WAIT_FOREVER && timeout_ms != 0) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += timeout_ms / 1000; + ts.tv_nsec += (timeout_ms % 1000) * 1000000; + + if (ts.tv_nsec >= 1000000000) + { + ts.tv_sec++; + ts.tv_nsec -= 1000000000; + } + } + + /* 轮询等待直到条件满足或超时 */ + while (1) + { + /* 判断是否满足等待条件 */ + if (opt & TASK_EVENT_FLAG_AND) + { + matched = (set == (p->bits & set)); + } + else + { + matched = (p->bits & set) != 0; + } + + if (matched) + { + /* 回传实际接收到的事件位 */ + if (recved) + { + *recved = p->bits & set; + } + + /* 如果设置了 CLEAR 标志,自动清除已匹配的位 */ + if (opt & TASK_EVENT_FLAG_CLEAR) + { + p->bits &= ~set; + } + + break; + } + + /* 非阻塞模式:立即返回失败 */ + if (timeout_ms == 0) + { + ret = -1; + + break; + } + + /* 等待条件变量 */ + if (timeout_ms == TASK_EVENT_WAIT_FOREVER) + { + ret = pthread_cond_wait(&p->cond, &p->lock); + } + else + { + ret = pthread_cond_timedwait(&p->cond, &p->lock, &ts); + + if (ret == ETIMEDOUT) + { + ret = -1; + + break; + } + } + + if (ret != 0) + { + break; + } + } + + pthread_mutex_unlock(&p->lock); + + return ret; +} + +/** + * @brief 清除指定事件位 + */ +int task_event_clear(stru_task_event_t p_event, uint32_t event) +{ + if (!p_event) + { + LOG_E("task_event_clear: p_event is NULL"); + + return -1; + } + + stru_task_event *p = (stru_task_event *)p_event; + + pthread_mutex_lock(&p->lock); + p->bits &= ~event; + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 查询当前事件位(非阻塞) + */ +uint32_t task_event_query(stru_task_event_t p_event) +{ + if (!p_event) + { + return 0; + } + + stru_task_event *p = (stru_task_event *)p_event; + + pthread_mutex_lock(&p->lock); + uint32_t bits = p->bits; + pthread_mutex_unlock(&p->lock); + + return bits; +} + +/******************************************************************************* + * 消息队列子系统的公开 API 实现 + ******************************************************************************/ + +/** + * @brief 创建定长消息队列 + */ +stru_task_msg_queue_t task_msg_queue_create(const char *name, + uint32_t msg_size, uint32_t msg_num) +{ + if (!name || msg_size == 0 || msg_num == 0) + { + LOG_E("task_msg_queue_create: invalid params"); + + return NULL; + } + + uint32_t total = msg_size * msg_num; + + stru_task_msg_queue *p = (stru_task_msg_queue *)calloc(1, sizeof(*p)); + + if (!p) + { + return NULL; + } + + p->buf = (uint8_t *)malloc(total); + + if (!p->buf) + { + free(p); + + return NULL; + } + + strncpy(p->name, name, sizeof(p->name) - 1); + p->msg_size = msg_size; + p->max_msgs = msg_num; + p->msg_count = 0; + p->head = 0; + p->tail = 0; + p->ref_count = 1; + + pthread_mutex_init(&p->lock, NULL); + pthread_cond_init(&p->cond, NULL); + + return (stru_task_msg_queue_t)p; +} + +/** + * @brief 销毁消息队列(带引用计数保护) + */ +int task_msg_queue_destroy(stru_task_msg_queue_t p_queue) +{ + if (!p_queue) + { + return -1; + } + + stru_task_msg_queue *p = (stru_task_msg_queue *)p_queue; + + pthread_mutex_lock(&p->lock); + + p->ref_count--; + + if (p->ref_count > 0) + { + pthread_mutex_unlock(&p->lock); + + return 0; + } + + pthread_mutex_unlock(&p->lock); + pthread_mutex_destroy(&p->lock); + pthread_cond_destroy(&p->cond); + free(p->buf); + free(p); + + return 0; +} + +/** + * @brief 发送消息(队列满时阻塞等待,无超时版本) + */ +int task_msg_queue_send(stru_task_msg_queue_t p_queue, const void *msg, + uint32_t size) +{ + if (!p_queue || !msg || size == 0) + { + return -1; + } + + stru_task_msg_queue *p = (stru_task_msg_queue *)p_queue; + + pthread_mutex_lock(&p->lock); + + /* 队列满则阻塞等待 */ + while (p->msg_count >= p->max_msgs) + { + pthread_cond_wait(&p->cond, &p->lock); + } + + /* 写入消息:先写长度前缀,再写消息体 */ + uint8_t *dst = p->buf + (p->tail * p->msg_size); + + memcpy(dst, &size, sizeof(size)); + dst += sizeof(size); + memcpy(dst, msg, size); + + p->tail = (p->tail + 1) % p->max_msgs; + p->msg_count++; + + pthread_cond_signal(&p->cond); + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 发送消息(带超时) + */ +int task_msg_queue_send_timeout(stru_task_msg_queue_t p_queue, const void *msg, + uint32_t size, uint32_t timeout_ms) +{ + if (!p_queue || !msg || size == 0) + { + return -1; + } + + stru_task_msg_queue *p = (stru_task_msg_queue *)p_queue; + struct timespec ts; + int ret = 0; + + pthread_mutex_lock(&p->lock); + + /* 非阻塞:队列满直接返回 */ + if (p->msg_count >= p->max_msgs) + { + if (timeout_ms == 0) + { + pthread_mutex_unlock(&p->lock); + + return -1; + } + + /* 计算绝对超时时间 */ + if (timeout_ms != TASK_EVENT_WAIT_FOREVER) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += timeout_ms / 1000; + ts.tv_nsec += (timeout_ms % 1000) * 1000000; + + if (ts.tv_nsec >= 1000000000) + { + ts.tv_sec++; + ts.tv_nsec -= 1000000000; + } + } + + /* 阻塞等待空间或超时 */ + while (p->msg_count >= p->max_msgs) + { + if (timeout_ms == TASK_EVENT_WAIT_FOREVER) + { + ret = pthread_cond_wait(&p->cond, &p->lock); + } + else + { + ret = pthread_cond_timedwait(&p->cond, &p->lock, &ts); + + if (ret == ETIMEDOUT) + { + pthread_mutex_unlock(&p->lock); + + return -1; + } + } + + if (ret != 0) + { + pthread_mutex_unlock(&p->lock); + + return -1; + } + } + } + + /* 写入消息 */ + uint8_t *dst = p->buf + (p->tail * p->msg_size); + + memcpy(dst, &size, sizeof(size)); + dst += sizeof(size); + memcpy(dst, msg, size); + + p->tail = (p->tail + 1) % p->max_msgs; + p->msg_count++; + + pthread_cond_signal(&p->cond); + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 接收消息(带超时) + */ +int task_msg_queue_recv(stru_task_msg_queue_t p_queue, void *msg, + uint32_t size, uint32_t timeout_ms) +{ + if (!p_queue || !msg || size == 0) + { + return -1; + } + + stru_task_msg_queue *p = (stru_task_msg_queue *)p_queue; + struct timespec ts; + int ret = 0; + uint32_t msg_len = 0; + uint8_t *src; + + pthread_mutex_lock(&p->lock); + + /* 计算绝对超时时间 */ + if (timeout_ms != TASK_EVENT_WAIT_FOREVER && timeout_ms != 0) + { + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_sec += timeout_ms / 1000; + ts.tv_nsec += (timeout_ms % 1000) * 1000000; + + if (ts.tv_nsec >= 1000000000) + { + ts.tv_sec++; + ts.tv_nsec -= 1000000000; + } + } + + /* 等待直到有消息或超时 */ + while (p->msg_count == 0) + { + if (timeout_ms == 0) + { + pthread_mutex_unlock(&p->lock); + + return -1; + } + + if (timeout_ms == TASK_EVENT_WAIT_FOREVER) + { + ret = pthread_cond_wait(&p->cond, &p->lock); + } + else + { + ret = pthread_cond_timedwait(&p->cond, &p->lock, &ts); + + if (ret == ETIMEDOUT) + { + pthread_mutex_unlock(&p->lock); + + return -1; + } + } + + if (ret != 0) + { + pthread_mutex_unlock(&p->lock); + + return -1; + } + } + + /* 读取消息:先读长度前缀,再读消息体 */ + src = p->buf + (p->head * p->msg_size); + + memcpy(&msg_len, src, sizeof(msg_len)); + src += sizeof(msg_len); + + /* 如果接收缓冲区不够大,截断 */ + if (msg_len > size) + { + msg_len = size; + } + + memcpy(msg, src, msg_len); + + p->head = (p->head + 1) % p->max_msgs; + p->msg_count--; + + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 尝试接收消息(非阻塞,队列空返回 -1) + */ +int task_msg_queue_try_recv(stru_task_msg_queue_t p_queue, void *msg, + uint32_t size) +{ + return task_msg_queue_recv(p_queue, msg, size, 0); +} + +/** + * @brief 获取当前队列消息数 + */ +uint32_t task_msg_queue_get_count(stru_task_msg_queue_t p_queue) +{ + if (!p_queue) + { + return 0; + } + + stru_task_msg_queue *p = (stru_task_msg_queue *)p_queue; + + pthread_mutex_lock(&p->lock); + uint32_t cnt = p->msg_count; + pthread_mutex_unlock(&p->lock); + + return cnt; +} + +/** + * @brief 获取队列剩余空间 + */ +uint32_t task_msg_queue_space(stru_task_msg_queue_t p_queue) +{ + if (!p_queue) + { + return 0; + } + + stru_task_msg_queue *p = (stru_task_msg_queue *)p_queue; + + pthread_mutex_lock(&p->lock); + uint32_t sp = p->max_msgs - p->msg_count; + pthread_mutex_unlock(&p->lock); + + return sp; +} + +/******************************************************************************* + * 定时器子系统的公开 API 实现 + ******************************************************************************/ + +/** + * @brief 创建定时器 + */ +stru_task_timer_t task_timer_create(const char *name, timer_func_cb fun_cb, + void *arg, uint32_t timeout_ms, int flags) +{ + if (!name || !fun_cb || timeout_ms == 0) + { + LOG_E("task_timer_create: invalid params"); + + return NULL; + } + + timer_manager_ensure(); + + stru_task_timer *p = (stru_task_timer *)calloc(1, sizeof(*p)); + + if (!p) + { + return NULL; + } + + strncpy(p->name, name, sizeof(p->name) - 1); + p->cb = fun_cb; + p->arg = arg; + p->timeout_ms = timeout_ms; + p->flags = flags; + p->active = 0; + p->ref_count = 1; + + p->timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); + + if (p->timerfd < 0) + { + LOG_E("timerfd_create failed"); + free(p); + + return NULL; + } + + pthread_mutex_init(&p->lock, NULL); + + return (stru_task_timer_t)p; +} + +/** + * @brief 启动定时器 + */ +int task_timer_start(stru_task_timer_t p_timer) +{ + if (!p_timer) + { + return -1; + } + + stru_task_timer *p = (stru_task_timer *)p_timer; + + while (g_timer_epfd < 0) { usleep(1000); } + + while (g_timer_epfd < 0) + { + usleep(1000); + } + + pthread_mutex_lock(&p->lock); + + /* 设置 timerfd 定时参数 */ + struct itimerspec its; + + memset(&its, 0, sizeof(its)); + its.it_value.tv_sec = p->timeout_ms / 1000; + its.it_value.tv_nsec = (p->timeout_ms % 1000) * 1000000; + + /* 周期模式下设置间隔 */ + if (p->flags & TASK_TIMER_FLAG_PERIODIC) + { + its.it_interval.tv_sec = p->timeout_ms / 1000; + its.it_interval.tv_nsec = (p->timeout_ms % 1000) * 1000000; + } + + timerfd_settime(p->timerfd, 0, &its, NULL); + + /* 加入 epoll 监听 */ + if (!p->running) + { + struct epoll_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = p; + + epoll_ctl(g_timer_epfd, EPOLL_CTL_ADD, p->timerfd, &ev); + p->running = 1; + } + + p->active = 1; + + /* 通过 eventfd 唤醒 epoll 线程 */ + uint64_t one = 1; + + write(g_timer_evtfd, &one, sizeof(one)); + + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 停止定时器 + */ +int task_timer_stop(stru_task_timer_t p_timer) +{ + if (!p_timer) + { + return -1; + } + + stru_task_timer *p = (stru_task_timer *)p_timer; + + pthread_mutex_lock(&p->lock); + + /* 从 epoll 移除 */ + if (p->running) + { + epoll_ctl(g_timer_epfd, EPOLL_CTL_DEL, p->timerfd, NULL); + p->running = 0; + } + + /* 停止 timerfd */ + struct itimerspec its; + + memset(&its, 0, sizeof(its)); + timerfd_settime(p->timerfd, 0, &its, NULL); + p->active = 0; + + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 重启定时器(可修改周期) + */ +int task_timer_restart(stru_task_timer_t p_timer, uint32_t timeout_ms) +{ + if (!p_timer || timeout_ms == 0) + { + return -1; + } + + stru_task_timer *p = (stru_task_timer *)p_timer; + + pthread_mutex_lock(&p->lock); + + p->timeout_ms = timeout_ms; + + /* 重新设置 timerfd */ + struct itimerspec its; + + memset(&its, 0, sizeof(its)); + its.it_value.tv_sec = timeout_ms / 1000; + its.it_value.tv_nsec = (timeout_ms % 1000) * 1000000; + + if (p->flags & TASK_TIMER_FLAG_PERIODIC) + { + its.it_interval.tv_sec = timeout_ms / 1000; + its.it_interval.tv_nsec = (timeout_ms % 1000) * 1000000; + } + + timerfd_settime(p->timerfd, 0, &its, NULL); + + /* 如果不在 epoll 中则加入 */ + if (!p->running) + { + struct epoll_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.events = EPOLLIN; + ev.data.ptr = p; + + epoll_ctl(g_timer_epfd, EPOLL_CTL_ADD, p->timerfd, &ev); + p->running = 1; + } + + p->active = 1; + + pthread_mutex_unlock(&p->lock); + + return 0; +} + +/** + * @brief 销毁定时器(带引用计数保护) + */ +int task_timer_destroy(stru_task_timer_t p_timer) +{ + if (!p_timer) + { + return -1; + } + + stru_task_timer *p = (stru_task_timer *)p_timer; + + pthread_mutex_lock(&p->lock); + + if (p->running) + { + epoll_ctl(g_timer_epfd, EPOLL_CTL_DEL, p->timerfd, NULL); + p->running = 0; + } + + close(p->timerfd); + p->active = 0; + + pthread_mutex_unlock(&p->lock); + pthread_mutex_destroy(&p->lock); + free(p); + + return 0; +} + +/** + * @brief 查询定时器是否在运行 + */ +int task_timer_is_active(stru_task_timer_t p_timer) +{ + if (!p_timer) + { + return 0; + } + + stru_task_timer *p = (stru_task_timer *)p_timer; + + pthread_mutex_lock(&p->lock); + int a = p->active; + pthread_mutex_unlock(&p->lock); + + return a; +}