docs: 创建完整 API 参考文档(9 个文档, 1005 行)
目录结构: docs/public/ 镜像 src/public/, 每个模块一个 API-xxx.md 文档内容: 模块概述+数据结构+接口详细说明+使用示例+依赖关系 覆盖模块: - docs/README.md (总索引, 依赖关系图) - myBase.h (公共宏/字节序/数据类型常量) - liblist (11 API, 侵入式链表, 含完整代码示例) - liblog (17 API, 异步日志, 消息池+批量+文件轮转) - libfunc (65 函数, 7 大分类, 分组文档) - libmd5 (4 API, RFC 1321, 流式计算示例) - libtask (21 API, 定时器+事件+消息队列, 三个独立示例) - libcJSON (开源库, 解析/生成 全流程示例) - libmy_xxhash (开源库, XXH32/XXH64 快速哈希) 文档规范已存入 /memories/doc-spec.md
This commit is contained in:
parent
aa97f72500
commit
44419ec729
|
|
@ -0,0 +1,66 @@
|
|||
# RTU_ALL_AI API 参考文档
|
||||
|
||||
> 生成日期: 2026-07-07
|
||||
> 项目: RTU_ALL_AI — C/C++ 嵌入式通讯装置示例工程
|
||||
|
||||
---
|
||||
|
||||
## 文档索引
|
||||
|
||||
### 基础公共库 (public/)
|
||||
|
||||
| 模块 | 文档 | 语言 | 说明 |
|
||||
|------|------|------|------|
|
||||
| myBase.h | [API-myBase.md](public/API-myBase.md) | C 头文件 | 公共宏、类型常量、字节序转换 |
|
||||
| liblist | [API-liblist.md](public/liblist/API-liblist.md) | 纯 C 头文件 | 侵入式双向循环链表 |
|
||||
| liblog | [API-liblog.md](public/liblog/API-liblog.md) | 纯 C | 异步日志系统 |
|
||||
| libfunc | [API-libfunc.md](public/libfunc/API-libfunc.md) | 纯 C | 65 个基础工具函数 |
|
||||
| libmd5 | [API-libmd5.md](public/libmd5/API-libmd5.md) | 纯 C | MD5 消息摘要 (RFC 1321) |
|
||||
| libtask | [API-libtask.md](public/libtask/API-libtask.md) | 纯 C | 定时器 + 事件 + 消息队列 |
|
||||
| libcJSON | [API-libcJSON.md](public/libcJSON/API-libcJSON.md) | 纯 C (开源库) | JSON 解析/生成 |
|
||||
| libmy_xxhash | [API-libmy_xxhash.md](public/libmy_xxhash/API-libmy_xxhash.md) | 纯 C (开源库) | xxHash 快速哈希 |
|
||||
|
||||
### 模块依赖关系图
|
||||
|
||||
```
|
||||
┌──────────┐
|
||||
│ myBase.h │ (颜色/大小端/类型常量)
|
||||
└────┬─────┘
|
||||
┌──────────────┼──────────────┐
|
||||
▼ ▼ ▼
|
||||
┌─────────┐ ┌─────────┐ ┌──────────┐
|
||||
│ liblist │ │ libfunc │ │ libmd5 │
|
||||
│ (链表) │ │ (65函数)│ │ (MD5) │
|
||||
└────┬────┘ └────┬────┘ └──────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────────────────┐
|
||||
│ liblog │ (异步日志,依赖
|
||||
│ (消息池+批量+文件轮转) │ liblist + libfunc)
|
||||
└─────────────────────────┘
|
||||
|
||||
┌──────────┐ ┌──────────────┐
|
||||
│ libcJSON │ │ libmy_xxhash │ (开源库,直接使用)
|
||||
└──────────┘ └──────────────┘
|
||||
|
||||
┌────────────────────────────────┐
|
||||
│ libtask │ (事件/定时器/消息队列)
|
||||
│ (timerfd + epoll + pthread) │
|
||||
└────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 构建与编译
|
||||
|
||||
```bash
|
||||
cd release
|
||||
./build.sh # x86 本地编译
|
||||
./build.sh arm # ARM 交叉编译
|
||||
```
|
||||
|
||||
### 编码规范
|
||||
|
||||
详见项目内存 `/memories/code-style.md`:
|
||||
- 一行一语句,`{}` 独占行,`}` 后空行,`return` 前空行
|
||||
- 运算符前后空格(`a + b`, `x << 8`),逗号分号后空格
|
||||
- 结构体 `stru_` 前缀,枚举 `enum_` 前缀
|
||||
- 注释使用 UTF-8 中文
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
# myBase.h — 公共基础定义 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
myBase.h 是所有模块共享的基础头文件。提供通用宏、类型别名、字节序转换、数据类型常量等。
|
||||
|
||||
## 终端颜色码
|
||||
|
||||
```c
|
||||
#define COLOR_RESET "\033[0m" // 重置
|
||||
#define COLOR_RED "\033[31m" // 红色
|
||||
#define COLOR_GREEN "\033[32m" // 绿色
|
||||
#define COLOR_YELLOW "\033[33m" // 黄色
|
||||
#define COLOR_BLUE "\033[34m" // 蓝色
|
||||
#define COLOR_MAGENTA "\033[35m" // 品红
|
||||
#define COLOR_CYAN "\033[36m" // 青色
|
||||
#define COLOR_WHITE "\033[37m" // 白色
|
||||
```
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
printf(COLOR_RED "错误: %s" COLOR_RESET "\n", "连接失败");
|
||||
```
|
||||
|
||||
## 文件名缩写
|
||||
|
||||
```c
|
||||
#define __SHORT_FILE__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__)
|
||||
```
|
||||
自动去掉文件路径前缀,跨平台兼容(Linux 用 `/`,Windows 用 `\`)。
|
||||
|
||||
## 简易日志宏
|
||||
|
||||
```c
|
||||
#define MY_LOG(color, level, fmt, ...) // 控制台日志(带颜色)
|
||||
#define MY_LOG_I(fmt, ...) // INFO(白色)
|
||||
#define MY_LOG_E(fmt, ...) // ERROR(红色)
|
||||
```
|
||||
|
||||
## LOCAL 修饰符
|
||||
|
||||
```c
|
||||
#define LOCAL static
|
||||
```
|
||||
语义化表示"文件内可见",等价于 `static`。
|
||||
|
||||
## 定长字符串类型
|
||||
|
||||
```c
|
||||
typedef char S_STR[64]; // 64 字节短字符串
|
||||
typedef char L_STR[128]; // 128 字节长字符串
|
||||
```
|
||||
|
||||
## 字节序转换宏
|
||||
|
||||
### uint16
|
||||
|
||||
| 宏 | 功能 |
|
||||
|----|------|
|
||||
| `BE16_GET(p)` | 大端字节序 → uint16 |
|
||||
| `BE16_SET(m, n)` | uint16 → 大端字节序 |
|
||||
| `LE16_GET(p)` | 小端字节序 → uint16 |
|
||||
| `LE16_SET(m, n)` | uint16 → 小端字节序 |
|
||||
|
||||
### int32
|
||||
|
||||
| 宏 | 功能 |
|
||||
|----|------|
|
||||
| `BE32_GET(p)` / `BE32_SET(m, n)` | 大端 int32 |
|
||||
| `LE32_GET(p)` / `LE32_SET(m, n)` | 小端 int32 |
|
||||
|
||||
### uint64
|
||||
|
||||
| 宏 | 功能 |
|
||||
|----|------|
|
||||
| `BE64_GET(p)` / `BE64_SET(m, n)` | 大端 uint64 |
|
||||
| `LE64_GET(p)` / `LE64_SET(m, n)` | 小端 uint64 |
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
uint8_t buf[4] = { 0x00, 0x00, 0x00, 0xFF };
|
||||
uint32_t val = BE32_GET(buf);
|
||||
printf("val = %u\n", val); // 255
|
||||
```
|
||||
|
||||
## 类型化数据存取
|
||||
|
||||
```c
|
||||
#define GET_BY_TYPE(p, type) (*(type *)(p))
|
||||
#define SET_BY_TYPE(p, v, type) (*(type *)(p) = *(type *)(v))
|
||||
```
|
||||
|
||||
## 数据类型常量(22 种,用于协议编解码)
|
||||
|
||||
| 常量 | 值 | 含义 | 常量 | 值 | 含义 |
|
||||
|------|-----|------|------|-----|------|
|
||||
| `DATA_TYPE_B` | 1 | bool | `DATA_TYPE_IP` | 100 | IP 地址 |
|
||||
| `DATA_TYPE_S8` | 43 | int8 | `DATA_TYPE_MAC` | 101 | MAC 地址 |
|
||||
| `DATA_TYPE_U8` | 32 | uint8 | `DATA_TYPE_C8` | 102 | char[8] |
|
||||
| `DATA_TYPE_S16` | 33 | int16 | `DATA_TYPE_C32` | 103 | char[32] |
|
||||
| `DATA_TYPE_U16` | 45 | uint16 | `DATA_TYPE_C64` | 104 | char[64] |
|
||||
| `DATA_TYPE_S32` | 2 | int32 | `DATA_TYPE_C128` | 105 | char[128] |
|
||||
| `DATA_TYPE_U32` | 35 | uint32 | `DATA_TYPE_C1` | 106 | char[1] |
|
||||
| `DATA_TYPE_L64` | 36 | int64 | `DATA_TYPE_STR` | 107 | string |
|
||||
| `DATA_TYPE_UL64` | 37 | uint64 | | | |
|
||||
| `DATA_TYPE_F32` | 38 | float | | | |
|
||||
| `DATA_TYPE_D64` | 39 | double | | | |
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: 标准 C/POSIX 头文件
|
||||
- **被依赖**: 所有模块
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
# libcJSON — JSON 解析/生成库 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
libcJSON 是开源的轻量级 JSON 解析/生成库(MIT 许可证),直接使用原工程版本。
|
||||
基于递归下降解析器 + 树状内存模型。支持 object/array/string/number/boolean/null。
|
||||
|
||||
## 数据结构
|
||||
|
||||
```c
|
||||
typedef enum
|
||||
{ CJSON_NULL = 0, CJSON_FALSE, CJSON_TRUE,
|
||||
CJSON_NUMBER, CJSON_STRING, CJSON_ARRAY, CJSON_OBJECT
|
||||
} enum_cjson_type;
|
||||
|
||||
typedef struct cjson
|
||||
{
|
||||
struct cjson *next, *prev; // 兄弟节点链表
|
||||
struct cjson *child; // 子节点(对象/数组的第一个子元素)
|
||||
enum_cjson_type type;
|
||||
char *key; // 对象键名
|
||||
char *val_str; // 字符串值
|
||||
double val_num; // 数值
|
||||
} stru_cjson;
|
||||
```
|
||||
|
||||
## 接口函数
|
||||
|
||||
### 解析与释放
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `cJSON_Parse(json)` | 解析 JSON 字符串,返回根节点 |
|
||||
| `cJSON_Delete(node)` | 递归释放整棵树 |
|
||||
|
||||
### 查询
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `cJSON_GetObjectItem(obj, key)` | 按 key 获取对象成员 |
|
||||
| `cJSON_GetArraySize(arr)` | 获取数组长度 |
|
||||
| `cJSON_GetArrayItem(arr, idx)` | 获取数组元素(0-based) |
|
||||
| `cJSON_GetStringValue(it)` | 获取字符串值 |
|
||||
| `cJSON_GetNumberValue(it)` | 获取数值 |
|
||||
|
||||
### 创建
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `cJSON_CreateObject()` | 创建空对象 `{}` |
|
||||
| `cJSON_CreateArray()` | 创建空数组 `[]` |
|
||||
| `cJSON_CreateString(s)` | 创建字符串节点 |
|
||||
| `cJSON_CreateNumber(n)` | 创建数值节点 |
|
||||
| `cJSON_CreateBool(b)` | 创建 true/false |
|
||||
| `cJSON_CreateNull()` | 创建 null |
|
||||
|
||||
### 修改
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `cJSON_AddItemToObject(obj, key, item)` | 向对象添加键值对 |
|
||||
| `cJSON_AddItemToArray(arr, item)` | 向数组追加元素 |
|
||||
| `cJSON_DeleteItemFromObject(obj, key)` | 删除对象成员 |
|
||||
|
||||
### 序列化
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `cJSON_Print(node)` | 序列化为紧凑 JSON 字符串(调用者 free) |
|
||||
|
||||
## 使用示例
|
||||
|
||||
```c
|
||||
#include "cJSON.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// --- 解析 JSON ---
|
||||
const char *json = "{\"name\":\"RTU\",\"addr\":1,\"items\":[1,2,3]}";
|
||||
stru_cjson *root = cJSON_Parse(json);
|
||||
|
||||
const char *name = cJSON_GetStringValue(cJSON_GetObjectItem(root, "name"));
|
||||
double addr = cJSON_GetNumberValue(cJSON_GetObjectItem(root, "addr"));
|
||||
|
||||
printf("name=%s, addr=%.0f\n", name, addr);
|
||||
// 输出: name=RTU, addr=1
|
||||
|
||||
// 遍历数组
|
||||
stru_cjson *arr = cJSON_GetObjectItem(root, "items");
|
||||
int n = cJSON_GetArraySize(arr);
|
||||
for (int i = 0; i < n; i++)
|
||||
{
|
||||
printf(" [%d] = %.0f\n", i,
|
||||
cJSON_GetNumberValue(cJSON_GetArrayItem(arr, i)));
|
||||
}
|
||||
|
||||
cJSON_Delete(root);
|
||||
|
||||
// --- 创建 JSON ---
|
||||
stru_cjson *obj = cJSON_CreateObject();
|
||||
cJSON_AddItemToObject(obj, "status", cJSON_CreateString("ok"));
|
||||
cJSON_AddItemToObject(obj, "code", cJSON_CreateNumber(200));
|
||||
|
||||
char *out = cJSON_Print(obj);
|
||||
printf("生成的 JSON: %s\n", out); // {"status":"ok","code":200}
|
||||
free(out);
|
||||
cJSON_Delete(obj);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: `stdlib.h`, `string.h`, `stdio.h`, `math.h`
|
||||
- **被依赖**: 配置文件解析、Web API 交互 等模块
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
# libfunc — 基础工具函数 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
libfunc 提供嵌入式开发中最常用的 65 个基础工具函数,分为 7 大类:
|
||||
1. 校验计算
|
||||
2. 字符串转换
|
||||
3. 时间处理
|
||||
4. 文件目录操作
|
||||
5. 进程管理
|
||||
6. 环境变量路径
|
||||
7. IPC 消息队列
|
||||
|
||||
## 一、校验计算 (6 函数)
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `func_cal_sum_byte(d, n)` | 8 位累加校验和 |
|
||||
| `func_cal_sum_word(d, n)` | 16 位累加校验和 |
|
||||
| `func_cal_crc16(d, n)` | CRC16 (Modbus 多项式 0xA001) |
|
||||
| `func_cal_crc32(d, n)` | CRC32 (标准多项式) |
|
||||
| `func_cal_file_crc16(path)` | 文件 CRC16(4K 缓冲区流式计算) |
|
||||
| `func_cal_file_crc32(path)` | 文件 CRC32 |
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
uint8_t d[] = { 0x01, 0x02, 0x03 };
|
||||
uint16_t crc = func_cal_crc16(d, 3);
|
||||
printf("CRC16 = 0x%04X\n", crc); // 0x6161
|
||||
```
|
||||
|
||||
## 二、字符串转换 (10 函数)
|
||||
|
||||
| 函数 | 参数 | 说明 |
|
||||
|------|------|------|
|
||||
| `func_hex_ch(c)` | char c | 十六进制字符 → 数值 |
|
||||
| `func_dec_ch(c)` | char c | 十进制字符 → 数值 |
|
||||
| `func_hex2dec(s)` | char *s | "FF" → 255 |
|
||||
| `func_dec2dec(s)` | char *s | "255" → 255(支持负号) |
|
||||
| `func_hex2buf(s, dst, len)` | 3 参数 | 十六进制字符串 → 字节缓冲 |
|
||||
| `func_dec2str(buf, sz, val, w)` | 4 参数 | int → 十进制字符串 |
|
||||
| `func_hex2str(buf, sz, val, w)` | 4 参数 | int → 十六进制字符串 |
|
||||
| `func_float2str(buf, sz, f, w)` | 4 参数 | float → 字符串 |
|
||||
| `func_buf2str(buf, sz, src, n)` | 4 参数 | 字节数组 → 十六进制字符串 |
|
||||
| `func_str2argv(s, argc, argv, max)` | 4 参数 | 按空格分割为 argc/argv |
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
char buf[64];
|
||||
func_dec2str(buf, sizeof(buf), 255, 4);
|
||||
printf("%s\n", buf); // "0255"
|
||||
|
||||
func_hex2str(buf, sizeof(buf), 255, 0);
|
||||
printf("%s\n", buf); // "FF"
|
||||
```
|
||||
|
||||
## 三、时间处理 (6 函数)
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `func_time_sys2str(buf, sz, ts)` | 系统时间 → "YYYY-MM-DD HH:MM:SS.mmm" |
|
||||
| `func_str2time_sys(s, ts)` | 字符串 → 系统时间 |
|
||||
| `func_get_time(t, type)` | 获取当前时间(type: 1=sys, 2=cal) |
|
||||
| `func_set_time(t, type)` | 设置系统时间(需 root) |
|
||||
| `func_time_sys2cal(src, dst)` | 系统时间 → 日历时间 |
|
||||
| `func_time_cal2sys(src, dst)` | 日历时间 → 系统时间 |
|
||||
|
||||
## 四、文件目录操作 (11 函数)
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `func_dir_exist(p)` | 目录是否存在 |
|
||||
| `func_make_dirs(p)` | 递归创建目录 |
|
||||
| `func_del_dirs(p)` | 递归删除目录 |
|
||||
| `func_del_dirs_cmd(p)` | 系统命令删除(rm -rf) |
|
||||
| `func_file_exist(p)` | 文件是否存在 |
|
||||
| `func_file_size(p)` | 获取文件大小(字节) |
|
||||
| `func_read_file(p, buf, cap, out)` | 读文件到预分配缓冲 |
|
||||
| `func_read_file_alloc(p, out)` | 读文件到动态分配缓冲 |
|
||||
| `func_write_file(p, buf, n)` | 写缓冲到文件 |
|
||||
| `func_read_file_info(p, info, check)` | 读结构化文件头(256B, CRC 校验) |
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
// 创建目录
|
||||
func_make_dirs("/tmp/myapp/config");
|
||||
|
||||
// 读取文件
|
||||
uint32_t size = 0;
|
||||
uint8_t *buf = func_read_file_alloc("/tmp/test.txt", &size);
|
||||
if (buf)
|
||||
{
|
||||
printf("Read %u bytes: %s\n", size, buf);
|
||||
free(buf);
|
||||
}
|
||||
```
|
||||
|
||||
## 五、进程管理 (9 函数)
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `func_proc_self_name(buf, sz)` | 获取本进程名(读 /proc/self/comm) |
|
||||
| `func_proc_name_by_pid(pid, buf, sz)` | PID → 进程名 |
|
||||
| `func_proc_pid()` | 获取本进程 PID |
|
||||
| `func_proc_pid_by_name(name)` | 进程名 → PID |
|
||||
| `func_proc_exist_by_pid(pid)` | 按 PID 判断进程存在 |
|
||||
| `func_proc_exist_by_name(name)` | 按名称判断进程存在 |
|
||||
| `func_proc_path_by_pid(pid, buf, sz)` | PID → 可执行文件路径 |
|
||||
| `func_proc_self_path(buf, sz)` | 本进程路径 |
|
||||
| `func_proc_self_dir(buf, sz)` | 本进程目录 |
|
||||
|
||||
## 六、环境变量路径 (12 函数)
|
||||
|
||||
| 函数 | 环境变量 |
|
||||
|------|---------|
|
||||
| `func_get_work_path(..)` | WORK_PATH |
|
||||
| `func_get_syscfg_path(..)` | SYS_CFG_PATH |
|
||||
| `func_get_app_root(..)` | APP_ROOT_PATH |
|
||||
| `func_get_his_root(..)` | HIS_ROOT_PATH |
|
||||
| `func_get_log_root(..)` | LOG_ROOT_PATH |
|
||||
| `func_get_dbc_root(..)` | DBC_ROOT_PATH |
|
||||
| `func_get_shell_path(..)` | SHELL_PATH |
|
||||
| `func_get_update_path(..)` | UPDATE_PATH |
|
||||
| `func_get_app_path(app, ..)` | 拼接: APP_ROOT/app |
|
||||
| `func_get_app_cfg(app, ext, ..)` | 拼接: APP_ROOT/app/ext |
|
||||
| `func_get_app_his(app, ..)` | 拼接: HIS_ROOT/app |
|
||||
| `func_get_app_log(app, ..)` | 拼接: LOG_ROOT/app |
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
char path[256];
|
||||
func_get_app_cfg("RTU", "config.json", path, sizeof(path));
|
||||
printf("Config path: %s\n", path); // /opt/RTU/config.json
|
||||
```
|
||||
|
||||
## 七、IPC 消息队列 (9 函数)
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `func_ipc_create_by_name(name, qid)` | 按名称创建 System V 消息队列 |
|
||||
| `func_ipc_create_by_pid(pid, qid)` | 按 PID 创建 |
|
||||
| `func_ipc_get_by_name(name, qid)` | 按名称获取 |
|
||||
| `func_ipc_get_by_pid(pid, qid)` | 按 PID 获取 |
|
||||
| `func_ipc_send_buf(qid, tx, n)` | 发送原始字节 |
|
||||
| `func_ipc_recv_buf(qid, rx, n)` | 接收原始字节 |
|
||||
| `func_ipc_send_msg(qid, msg)` | 发送结构体消息 |
|
||||
| `func_ipc_recv_msg(qid, msg)` | 接收结构体消息 |
|
||||
| `func_ipc_delete(qid)` | 删除队列 |
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: myBase.h
|
||||
- **被依赖**: liblog (进程路径), 所有需要 CRC/文件/进程操作的模块
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
# liblist — 侵入式双向循环链表 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
liblist 是 Linux 内核风格的双向循环链表,纯头文件实现,C/C++ 兼容。
|
||||
所有增删操作 O(1),遍历 O(n)。核心思想:将 `struct list_head` 嵌入宿主结构体,
|
||||
通过 `offsetof` 从链表节点指针反推宿主指针。
|
||||
|
||||
## 数据结构
|
||||
|
||||
```c
|
||||
struct list_head
|
||||
{
|
||||
struct list_head *next; // 后继节点
|
||||
struct list_head *prev; // 前驱节点
|
||||
};
|
||||
```
|
||||
|
||||
## 接口函数
|
||||
|
||||
### 初始化
|
||||
|
||||
#### LIST_HEAD(name)
|
||||
```c
|
||||
#define LIST_HEAD(name) struct list_head name = LIST_HEAD_INIT(name)
|
||||
```
|
||||
编译期定义并初始化一个链表头。
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
LIST_HEAD(my_list); // 定义 my_list 并初始化为空链表
|
||||
```
|
||||
|
||||
#### INIT_LIST_HEAD(h)
|
||||
```c
|
||||
void INIT_LIST_HEAD(struct list_head *h);
|
||||
```
|
||||
运行时初始化一个已存在的链表头。
|
||||
|
||||
**示例**:
|
||||
```c
|
||||
struct list_head head;
|
||||
INIT_LIST_HEAD(&head);
|
||||
```
|
||||
|
||||
### 添加
|
||||
|
||||
#### list_add(node, head)
|
||||
头插法:将 node 插入到 head 之后(作为第一个元素)。
|
||||
|
||||
```c
|
||||
void list_add(struct list_head *node, struct list_head *head);
|
||||
```
|
||||
|
||||
#### list_add_tail(node, head)
|
||||
尾插法:将 node 插入到 head 之前(作为最后一个元素)。
|
||||
|
||||
```c
|
||||
void list_add_tail(struct list_head *node, struct list_head *head);
|
||||
```
|
||||
|
||||
### 删除
|
||||
|
||||
#### list_del(entry)
|
||||
从链表中移除节点(不释放内存)。
|
||||
|
||||
#### list_del_init(entry)
|
||||
移除节点并重新初始化为自环,防止后续误操作导致悬空指针。
|
||||
|
||||
### 移动
|
||||
|
||||
#### list_move(list, head)
|
||||
将节点移动到新链表头部。
|
||||
|
||||
#### list_move_tail(list, head)
|
||||
将节点移动到新链表尾部。
|
||||
|
||||
### 替换
|
||||
|
||||
#### list_replace(old, node)
|
||||
用 node 替换 old 的位置。
|
||||
|
||||
#### list_replace_init(old, node)
|
||||
替换后初始化被替换节点。
|
||||
|
||||
### 判断
|
||||
|
||||
#### list_empty(head)
|
||||
判断链表是否为空(头节点的 next 指向自身即为空)。
|
||||
|
||||
#### list_is_linked(entry)
|
||||
判断节点是否已链入某个链表(非自环即为已链接)。
|
||||
|
||||
### 节点转宿主
|
||||
|
||||
#### list_entry(ptr, type, member)
|
||||
```c
|
||||
#define list_entry(ptr, type, member) \
|
||||
((type *)((char *)(ptr) - offsetof(type, member)))
|
||||
```
|
||||
从链表节点指针取回宿主结构体指针。
|
||||
|
||||
#### list_first_entry(head, type, member)
|
||||
获取第一个宿主元素。
|
||||
|
||||
#### list_last_entry(head, type, member)
|
||||
获取最后一个宿主元素。
|
||||
|
||||
#### list_first_entry_or_null(head, type, member)
|
||||
安全获取第一个元素(链表空返回 NULL)。
|
||||
|
||||
### 遍历
|
||||
|
||||
#### list_for_each(pos, head)
|
||||
遍历链表节点(仅获取 `struct list_head *` 指针)。
|
||||
|
||||
#### list_for_each_safe(pos, n, head)
|
||||
安全遍历(可在遍历中删除当前节点 pos)。
|
||||
|
||||
#### list_for_each_entry(pos, head, member)
|
||||
遍历宿主元素,最常用。
|
||||
|
||||
#### list_for_each_entry_safe(pos, n, head, member)
|
||||
安全遍历宿主元素(可在遍历中删除 pos)。
|
||||
|
||||
### 拼接
|
||||
|
||||
#### list_splice_init(src, dst)
|
||||
将 src 链表拼接到 dst 头部,src 被清空。
|
||||
|
||||
## 使用示例
|
||||
|
||||
```c
|
||||
#include "myBase.h"
|
||||
#include "list.h"
|
||||
|
||||
// 定义宿主结构体
|
||||
struct sensor
|
||||
{
|
||||
int id;
|
||||
float value;
|
||||
struct list_head node; // 嵌入的链表节点
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// 定义链表头
|
||||
LIST_HEAD(sensor_list);
|
||||
|
||||
// 创建 3 个传感器
|
||||
struct sensor s1 = { .id = 1, .value = 25.5 };
|
||||
struct sensor s2 = { .id = 2, .value = 30.0 };
|
||||
struct sensor s3 = { .id = 3, .value = 22.1 };
|
||||
|
||||
// 尾插
|
||||
list_add_tail(&s1.node, &sensor_list);
|
||||
list_add_tail(&s2.node, &sensor_list);
|
||||
list_add_tail(&s3.node, &sensor_list);
|
||||
|
||||
// 遍历并打印
|
||||
struct sensor *pos;
|
||||
list_for_each_entry(pos, &sensor_list, node)
|
||||
{
|
||||
printf("sensor %d: %.1f\n", pos->id, pos->value);
|
||||
}
|
||||
// 输出:
|
||||
// sensor 1: 25.5
|
||||
// sensor 2: 30.0
|
||||
// sensor 3: 22.1
|
||||
|
||||
// 安全删除所有节点
|
||||
struct sensor *tmp;
|
||||
list_for_each_entry_safe(pos, tmp, &sensor_list, node)
|
||||
{
|
||||
printf("removing sensor %d\n", pos->id);
|
||||
list_del(&pos->node);
|
||||
free(pos); // 如果是动态分配的
|
||||
}
|
||||
|
||||
printf("list empty: %d\n", list_empty(&sensor_list)); // 1
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: `<stddef.h>` (offsetof)
|
||||
- **被依赖**: liblog, libdatacenter, 所有需要链表管理的模块
|
||||
|
|
@ -0,0 +1,106 @@
|
|||
# liblog — 异步日志系统 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
liblog 是嵌入式装置专用的异步日志系统。支持 INFO/ERROR 两级日志,非阻塞写入。
|
||||
首次调用自动初始化(pthread_once 懒启动)。控制台支持 ANSI 彩色输出,
|
||||
文件支持按大小自动轮转。
|
||||
|
||||
**核心特性**:
|
||||
- **消息池预分配**:10000 条消息槽位,运行时零 malloc
|
||||
- **批量消费**:工作线程每次最多取 100 条,批量 I/O 减少系统调用
|
||||
- **生产者-消费者模型**:`log_prt()` 入队(生产者)→ 工作线程出队写入(消费者)
|
||||
- **文件轮转**:单文件超过 10MB 自动重命名为 `.1 → .2 → ... → .5`
|
||||
|
||||
## 常量与宏
|
||||
|
||||
| 宏 | 值 | 说明 |
|
||||
|----|-----|------|
|
||||
| `LOG_INFO` | 0 | INFO 级别(白色) |
|
||||
| `LOG_ERROR` | 1 | ERROR 级别(红色) |
|
||||
| `LOG_I(fmt, ...)` | — | INFO 便捷宏(自动填充文件名/函数名/行号) |
|
||||
| `LOG_E(fmt, ...)` | — | ERROR 便捷宏 |
|
||||
|
||||
## 接口函数
|
||||
|
||||
### log_init(dir)
|
||||
```c
|
||||
int log_init(const char *dir);
|
||||
```
|
||||
手动初始化日志系统(可选)。首次调用 `log_prt()` 时会自动触发。
|
||||
- `dir`: 日志目录路径,`NULL` 则默认 `/tmp/logs`
|
||||
- 返回: 0 成功
|
||||
|
||||
### log_prt(level, file, func, line, fmt, ...)
|
||||
```c
|
||||
void log_prt(uint32_t level, const char *file, const char *func,
|
||||
uint32_t line, const char *fmt, ...);
|
||||
```
|
||||
核心日志函数(非阻塞)。从消息池取空闲块 → 填充时间/来源 → 入队 → 立即返回。
|
||||
|
||||
**参数**:
|
||||
- `level`: `LOG_INFO` 或 `LOG_ERROR`
|
||||
- `file`: `__FILE__`(源文件名)
|
||||
- `func`: `__FUNCTION__`(函数名)
|
||||
- `line`: `__LINE__`(行号)
|
||||
- `fmt, ...`: printf 格式化
|
||||
|
||||
### log_file_on / log_file_off
|
||||
```c
|
||||
void log_file_on(void);
|
||||
void log_file_off(void);
|
||||
```
|
||||
开启/关闭文件写入。默认关闭,通过 `log_init()` 开启。
|
||||
|
||||
### log_console_on / log_console_off
|
||||
```c
|
||||
void log_console_on(void);
|
||||
void log_console_off(void);
|
||||
```
|
||||
开启/关闭控制台输出。默认开启。
|
||||
|
||||
### log_flush(void)
|
||||
```c
|
||||
void log_flush(void);
|
||||
```
|
||||
阻塞等待消息队列清空(所有日志写入完成)。
|
||||
|
||||
### log_cleanup(void)
|
||||
```c
|
||||
void log_cleanup(void);
|
||||
```
|
||||
停止工作线程、关闭文件句柄、释放消息池。
|
||||
|
||||
## 使用示例
|
||||
|
||||
```c
|
||||
#include "myLog.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// 手动初始化(可选),指定日志目录
|
||||
log_init("/var/log/myapp");
|
||||
|
||||
// INFO 日志
|
||||
LOG_I("系统启动完成, CPU=%.1f%%, MEM=%uMB", 45.2, 128);
|
||||
|
||||
// ERROR 日志(红色输出)
|
||||
LOG_E("通讯超时: channel=%d, addr=%u", 3, 0x01);
|
||||
|
||||
// 开关控制
|
||||
log_console_off(); // 关闭控制台(仅写文件)
|
||||
LOG_I("仅文件输出");
|
||||
log_console_on();
|
||||
|
||||
// 清理
|
||||
log_flush();
|
||||
log_cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: liblist (消息队列链表), libfunc (进程路径获取)
|
||||
- **被依赖**: 所有需要日志的模块
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
# libmd5 — MD5 消息摘要 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
libmd5 实现了 RFC 1321 定义的 MD5 消息摘要算法。128 位输出,支持流式输入
|
||||
(分多次调用 `md5_update`)。提供 `md5_string` 便捷函数一步完成字符串 MD5 计算。
|
||||
|
||||
## 数据结构
|
||||
|
||||
```c
|
||||
typedef struct
|
||||
{
|
||||
uint32_t state[4]; // A, B, C, D 四个 32 位状态寄存器
|
||||
uint32_t count[2]; // 位计数(低 32 位, 高 32 位)
|
||||
unsigned char buf[64]; // 待处理数据缓冲区(64 字节)
|
||||
} stru_md5_ctx;
|
||||
```
|
||||
|
||||
## 接口函数
|
||||
|
||||
### md5_start(ctx)
|
||||
```c
|
||||
void md5_start(stru_md5_ctx *ctx);
|
||||
```
|
||||
初始化上下文,设置 RFC 1321 标准魔数:
|
||||
`A=0x67452301 B=0xefcdab89 C=0x98badcfe D=0x10325476`。
|
||||
|
||||
### md5_update(ctx, data, len)
|
||||
```c
|
||||
void md5_update(stru_md5_ctx *ctx, const unsigned char *data, int len);
|
||||
```
|
||||
输入数据,可多次调用支持流式处理。内部按 64 字节分块,填满即变换。
|
||||
|
||||
### md5_final(ctx, result)
|
||||
```c
|
||||
void md5_final(stru_md5_ctx *ctx, unsigned char result[16]);
|
||||
```
|
||||
完成计算,输出 16 字节 MD5 摘要。内部自动填充 0x80+零+位计数。
|
||||
|
||||
### md5_string(input, output)
|
||||
```c
|
||||
void md5_string(const char *input, char output[33]);
|
||||
```
|
||||
单次调用便捷函数:输入字符串 → 输出 32 字符大写十六进制 + '\0'。
|
||||
|
||||
## 使用示例
|
||||
|
||||
```c
|
||||
#include "myMd5.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// 方式 1: 单次调用
|
||||
char hex[33];
|
||||
md5_string("hello", hex);
|
||||
printf("MD5(hello) = %s\n", hex);
|
||||
// 输出: MD5(hello) = 5D41402ABC4B2A76B9719D911017C592
|
||||
|
||||
// 方式 2: 流式计算(大文件场景)
|
||||
stru_md5_ctx ctx;
|
||||
unsigned char digest[16];
|
||||
|
||||
md5_start(&ctx);
|
||||
md5_update(&ctx, (unsigned char *)"hello ", 6);
|
||||
md5_update(&ctx, (unsigned char *)"world", 5);
|
||||
md5_final(&ctx, digest);
|
||||
|
||||
printf("流式: ");
|
||||
for (int i = 0; i < 16; i++) printf("%02X", digest[i]);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: 无
|
||||
- **被依赖**: 文件校验、协议认证 等模块
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# libmy_xxhash — xxHash 快速哈希 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
xxHash 是极速非加密哈希算法(BSD 2-Clause 许可证),直接使用原工程版本。
|
||||
提供 XXH32(32 位)和 XXH64(64 位)两种哈希。用于数据中心信号点快速索引。
|
||||
|
||||
## 接口函数
|
||||
|
||||
### XXH32(input, len, seed)
|
||||
```c
|
||||
uint32_t XXH32(const void *input, size_t len, uint32_t seed);
|
||||
```
|
||||
计算 32 位哈希值。`seed` 通常传 0。
|
||||
|
||||
### XXH64(input, len, seed)
|
||||
```c
|
||||
uint64_t XXH64(const void *input, size_t len, uint64_t seed);
|
||||
```
|
||||
计算 64 位哈希值。
|
||||
|
||||
## 使用示例
|
||||
|
||||
```c
|
||||
#include "xxhash.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
const char *data = "hello world";
|
||||
|
||||
uint32_t h32 = XXH32(data, strlen(data), 0);
|
||||
uint64_t h64 = XXH64(data, strlen(data), 0);
|
||||
|
||||
printf("XXH32 = 0x%08X\n", h32);
|
||||
printf("XXH64 = 0x%016llX\n", (unsigned long long)h64);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
# libtask — 任务框架 API 参考
|
||||
|
||||
## 模块概述
|
||||
|
||||
libtask 是嵌入式装置的通用任务调度框架,包含三个子系统:
|
||||
- **定时器**:基于 timerfd + epoll 精确毫秒级定时
|
||||
- **事件**:基于位图 + pthread 条件变量的同步原语
|
||||
- **消息队列**:基于环形缓冲区的线程安全 FIFO
|
||||
|
||||
## 常量与类型
|
||||
|
||||
### 定时器标志
|
||||
| 宏 | 值 | 说明 |
|
||||
|----|-----|------|
|
||||
| `TASK_TIMER_FLAG_ONCE` | 0x01 | 单次触发 |
|
||||
| `TASK_TIMER_FLAG_PERIODIC` | 0x02 | 周期触发 |
|
||||
|
||||
### 事件标志
|
||||
| 宏 | 值 | 说明 |
|
||||
|----|-----|------|
|
||||
| `TASK_EVENT_WAIT_FOREVER` | 0xFFFFFFFF | 永久等待 |
|
||||
| `TASK_EVENT_FLAG_AND` | 0x01 | AND 模式(所有位都置位) |
|
||||
| `TASK_EVENT_FLAG_OR` | 0x02 | OR 模式(任意位置位) |
|
||||
| `TASK_EVENT_FLAG_CLEAR` | 0x04 | 接收后自动清除 |
|
||||
|
||||
### 回调类型
|
||||
```c
|
||||
typedef void (*timer_func_cb)(void *arg);
|
||||
```
|
||||
|
||||
### 不透明句柄
|
||||
```c
|
||||
typedef void *stru_task_timer_t;
|
||||
typedef void *stru_task_event_t;
|
||||
typedef void *stru_task_msg_queue_t;
|
||||
```
|
||||
|
||||
## 接口函数
|
||||
|
||||
### 通用延时
|
||||
|
||||
#### task_sleep_ms(ms)
|
||||
毫秒级精度延时(内部使用 nanosleep)。
|
||||
|
||||
### 定时器
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `task_timer_create(name, cb, arg, timeout_ms, flags)` | 创建定时器(不自动启动) |
|
||||
| `task_timer_start(pt)` | 启动 |
|
||||
| `task_timer_stop(pt)` | 停止 |
|
||||
| `task_timer_restart(pt, timeout_ms)` | 重启(可改周期) |
|
||||
| `task_timer_destroy(pt)` | 销毁 |
|
||||
| `task_timer_is_active(pt)` | 查询运行状态 |
|
||||
|
||||
### 事件
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `task_event_create(name)` | 创建事件对象 |
|
||||
| `task_event_destroy(pe)` | 销毁 |
|
||||
| `task_event_send(pe, bits)` | 发送(置位+广播) |
|
||||
| `task_event_recv(pe, set, opt, timeout_ms, recved)` | 等待 |
|
||||
| `task_event_clear(pe, bits)` | 清除位 |
|
||||
| `task_event_query(pe)` | 查询当前位(非阻塞) |
|
||||
|
||||
### 消息队列
|
||||
|
||||
| 函数 | 说明 |
|
||||
|------|------|
|
||||
| `task_msg_queue_create(name, msg_size, msg_num)` | 创建 |
|
||||
| `task_msg_queue_destroy(pq)` | 销毁 |
|
||||
| `task_msg_queue_send(pq, msg, size)` | 发送(阻塞) |
|
||||
| `task_msg_queue_send_timeout(pq, msg, size, timeout_ms)` | 发送(超时) |
|
||||
| `task_msg_queue_recv(pq, msg, size, timeout_ms)` | 接收(超时) |
|
||||
| `task_msg_queue_try_recv(pq, msg, size)` | 非阻塞接收 |
|
||||
| `task_msg_queue_get_count(pq)` | 获取消息数 |
|
||||
| `task_msg_queue_space(pq)` | 获取剩余空间 |
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 定时器
|
||||
```c
|
||||
#include "myTask.h"
|
||||
#include <stdio.h>
|
||||
|
||||
static int tick_count = 0;
|
||||
|
||||
void on_tick(void *arg)
|
||||
{
|
||||
tick_count++;
|
||||
printf("定时器触发: %d 次\n", tick_count);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
// 创建周期定时器:每 100ms 触发一次
|
||||
stru_task_timer_t pt = task_timer_create(
|
||||
"heartbeat", on_tick, NULL, 100, TASK_TIMER_FLAG_PERIODIC
|
||||
);
|
||||
|
||||
task_timer_start(pt);
|
||||
task_sleep_ms(500); // 等待 500ms(预计触发 5 次)
|
||||
task_timer_destroy(pt);
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
### 事件
|
||||
```c
|
||||
stru_task_event_t pe = task_event_create("ev1");
|
||||
|
||||
// 线程 A: 发送事件
|
||||
task_event_send(pe, 0x03); // 设置 bit0 和 bit1
|
||||
|
||||
// 线程 B: 等待事件(OR 模式 + 自动清除)
|
||||
uint32_t recved = 0;
|
||||
task_event_recv(pe, 0x03,
|
||||
TASK_EVENT_FLAG_OR | TASK_EVENT_FLAG_CLEAR,
|
||||
TASK_EVENT_WAIT_FOREVER, &recved);
|
||||
printf("收到事件: 0x%02X\n", recved); // 0x03
|
||||
|
||||
task_event_destroy(pe);
|
||||
```
|
||||
|
||||
### 消息队列
|
||||
```c
|
||||
// 创建队列:每条 64 字节,容量 10 条
|
||||
stru_task_msg_queue_t pq = task_msg_queue_create("q1", 64, 10);
|
||||
|
||||
char tx[] = "Hello";
|
||||
char rx[64];
|
||||
|
||||
task_msg_queue_send(pq, tx, 6); // 发送
|
||||
task_msg_queue_recv(pq, rx, 64, 1000); // 接收(1 秒超时)
|
||||
|
||||
printf("收到: %s, 队列中: %u 条\n", rx, task_msg_queue_get_count(pq));
|
||||
task_msg_queue_destroy(pq);
|
||||
```
|
||||
|
||||
## 依赖关系
|
||||
|
||||
- **依赖**: liblog (错误日志)
|
||||
- **系统依赖**: `<sys/timerfd.h>`, `<sys/epoll.h>`, `<sys/eventfd.h>`, `<pthread.h>`
|
||||
- **被依赖**: 所有需要定时/同步/通讯的模块
|
||||
Loading…
Reference in New Issue