# lb_base **Repository Path**: litebmc/lb_base ## Basic Information - **Project Name**: lb_base - **Description**: litebmc的框架基础库(base library),是接口代码自动生成需要信赖的基础库,由上层应用注册属性变更、信号发送 、信号订阅、方法调用、读写属性方法以及向上层返回已注册的interface基本信息。 - **Primary Language**: Unknown - **License**: LGPL-2.1 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2023-05-23 - **Last Updated**: 2026-06-09 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## DBUS通信模型 DBUS是一种进程间通信机制,连接到总线的进程可通过总线接收或传递消息,总线收到消息时,根据不同的消息类型进行不同的处理,DBUS模型中存在服务端和客户端解决,服务端实现接口,客户端使用接口,D-Bus 规范参考:https://dbus.freedesktop.org/doc/dbus-specification.html#Introduction ## 接口编程模型 DBUS定义的基于接口的编程模型,参考[Introspection Data Format](https://dbus.freedesktop.org/doc/dbus-specification.html#Introspection%20Data%20Format)。 有很多基础库实现dbus交互,如DBusConnection(libdbus)、GDBusConnection(glib2.0)、sdbus(libsystemd)等,对于新手来说,熟练使用这些库还是存在不小的挑战。为此,litebmc.com设计了`litebmc/lbkit`代码自动生成工具,支持将[IDF文件: Interface description file](/docs/models/idf.md)转换成C代码,结合lb_base和lb_core简化dbus属性查询设置、对象注册、方法调用、信号收发逻辑。 实际上,dbus定义的接口、对象、属性、方法、信号模型足够通用,可以承载在其它总线上。为简化litebmc的依赖关系管理,减少依赖变更的影响,litebmc定义了[lb_base](https://gitee.com/litebmc/lb_base),该库仅实现基础模型,不承载具体总线实现,基于IDF生成的C代码只依赖lb_base,不依赖具体的接口实现[lb_core](https://gitee.com/litebmc/lb_core)。 lb_base定义了接口编程模型,为代码自动生成工具接口描述文件(与dbus的自举文件相同)生成C代码。 ```txt -------------- -------------- ----------------------------------------------------------------------------------- | server app | | client app | | LBImpl 通用dbus接口抽象(由lb_core具体实现dbus对象管理、方法路径、信号订阅、属性同步等功能) | -------------- -------------- ----------------------------------------------------------------------------------- | | | | # [服务端]发送属性变更事件 | | | | | property_changed(object, pop): void | V V V | # [服务端]信号发送函数 | ---------- -------------- -------------- | emit_signal(object, dest, signal, msg, error): bool | | plugin |-->| server lib | | client lib | | # [客户端]订阅intf接口的信号,用于监听服务端发送的信号 | ---------- -------------- -------------- | subscribe_signal(intf, bus, signal, object_path, arg0, handle, user_data): uint | | | | # [客户端]取消订阅,入参是订阅时返回的id | | | | unsubscribe_signal(id) | V V _______| # [客户端]调用服务端方法 | -------------- / | call_method(object, method, req, rsp, timeout_msec, error): gint | | public lib | / | # 属性读函数:服务端读内存,客户端属性有变更事件的读内存,无变更事件的调用dbus接口查询无端值 | -------------- / | read_property(object, prop, value, error): gint | | / | # 属性写函数: 服务端直接写内存并触发变更事件,客户端调用服务端属性设置接口 | V / | write_property(object, prop, value, error): gint | -------------- / ------------------------------------------------------------------------------------ | lb_base | ________/ -------------- ``` - lb_base: 定义了LBImpl接口模型,定义了dbus接口通信所需的回调函数,由lb_core模块负责实现,代码仓地址: https://gitee.com/litebmc/lb_base - lb_core: 对GDbusConnection(glib2.0)进行了二次封装,实现lb_base定义的名为`LBImpl `的接口函数,代码仓地址: https://gitee.com/litebmc/lb_core - idf文件: Interface description file,描述litebmc的(dbus)接口文件,支持描述dbus接口的properties、methods、signals以及配套的structures、enumerations、dictionaries、errors基本数据类型。特别的,支持描述接口需要实现的plugin事件等。IDF接口统一存储在interfaces代码仓: https://gitee.com/litebmc/interfaces/tree/master/dbus - server lib、client lib、和public lib: 由lbkit工具读取IDF文件自动生成的三个lib库,分别对应服务端实现、客户端实现以及公共库,这三个库最终会生成三个conan包,组件实现时只需要依赖conan包。conan仓地址: https://art.litebmc.com/artifactory/api/conan/center。 - server app和client app: 实现具体的服务端和客户端业务,服务端创建对象,提供方法实现,发送信号;客户端获取对象后调用方法或监听信号,APP示例: https://gitee.com/litebmc/lb_example_app - plugin lib: 以动态库形式实现idf定义的plugin插件功能,server_app启动时会尝试加载server lib定义的plugin信息加载插件,server_app实现dbus接口时需要在合适的时机调用插件方法,插件示例: https://gitee.com/litebmc/lb_example_plugin ## 日志功能模块 lb_base 内置日志模块(`inc/lb_log.h`、`src/lb_log.c`),提供分级日志输出、多路由分发、异步限流和自动刷盘功能。 ### 环境变量 日志模块在构造阶段(`constructor(101)`)解析以下环境变量: | 环境变量 | 用途 | 取值 | |----------|------|------| | `LOG_LEVEL` | 日志等级过滤 | `mass`、`debug`、`info`、`warn`、`error` | | `LOG_TYPE` | 输出路由控制 | `stdout`(控制台)、`file`(文件)、其它值默认 syslog | | `ROOTFS_DIR` | 开发者测试时日志文件前缀 | 目录路径,如 `/tmp/rootfs` | **注意**:`LOG_TYPE` 仅 `stdout`/`file` 作为输出路由关键字;如果 `LOG_TYPE` 设置为 `debug`/`info`/`mass` 等非路由值,则路由保持默认 syslog,不会作为日志等级使用。日志等级由 `LOG_LEVEL` 单独控制。 ### 配置 API ```c // 设置/获取日志等级 void lb_log_set_level(int level); // level 取值范围 LOG_EMERG ~ LOG_MASS gint lb_log_get_level(void); // 设置/获取输出类型 void lb_log_set_type(LOG_TYPE type); LOG_TYPE lb_log_get_type(void); // 设置 syslog 服务名(自动调用 openlog) void lb_log_set_service(const char *service); // 控制 log_alert 是否触发 abort(仅 Debug 构建生效,Release 构建始终 abort) void lb_log_set_alert_abort(gboolean is_abort); // 强制刷新缓冲区中的日志 void lb_log_flush(void); ``` ### 限流机制 日志模块内置异步限流线程,防止日志洪泛导致性能问题: - **免费配额**:每个日志位置(按行号取模分槽)前 15 条(`REC_UNLIMIT_CNT`)无限制打印 - **限流周期**:生产环境 300 秒(`REC_LIMIT_DURATION`),测试环境 1 秒 - **限流计数**:同一位置日志到达 1000 条(`REC_LIMIT_CNT`)或超时后触发一次汇总打印 - **汇总格式**:触发限流时打印 `[repeated N times in Ss]` 标记,显示被合并的日志数量和时间跨度 - **自动刷盘**:后台线程每 5 秒扫描一次槽位,清理超时记录并打印最后一条合并日志(标记 `[flush]`) 限流宏用于条件性抑制重复日志: ```c // cond 为真时打印一条日志,之后连续的相同条件不再重复打印,直到条件变为假后才允许下次打印 log_limit(error, ret != 0, "operation failed, ret=%d", ret); ``` ### 文件日志特性 - **路径**:默认写入 `/var/log/litebmc.app.log` - **开发者测试**:设置 `ROOTFS_DIR` 环境变量后路径拼接为 `$ROOTFS_DIR/var/log/litebmc.app.log` - **原子写入**:单行日志 ≤4096 字节(PIPE_BUF),`write()` 配合 `O_APPEND` 保证多进程写入安全 - **自动创建**:日志目录不存在时自动以 0755 权限递归创建 - **降级策略**:文件打开失败时自动回退到 syslog 并打印警告 ### 使用示例 ```c #include "lb_base.h" // 初始化日志等级和输出类型 lb_log_set_level(LOG_DEBUG); lb_log_set_type(LOG_TO_CONSOLE); // 普通日志 log_info("Service started, version=%s", VERSION); log_debug("Processing request id=%u", req_id); log_warn("Resource usage exceeds %d%%", threshold); log_error("Failed to connect to %s: %s", host, strerror(errno)); log_alert("Critical corruption detected, aborting"); // 条件限流日志:cond 为真时打印,连续相同条件只打印一次 log_limit(error, !dbus_connected, "dbus connection lost"); log_limit(warn, mem_available <= MIN_MEM, "memory low: %lu bytes free", mem_free); // 刷新日志缓冲区(应用退出前调用) lb_log_flush(); ```