Skip to content

Latest commit

 

History

History
370 lines (242 loc) · 6.14 KB

File metadata and controls

370 lines (242 loc) · 6.14 KB

常见问题 (FAQ)

通用问题

Q: 这个项目解决什么问题?

A: 传统 logcat 在高频日志场景下有以下问题:

  • 每条日志需要多次系统调用
  • 多消费者时重复读取和解析
  • 延迟高(10-50ms)
  • CPU 占用高

logcat_daemon 通过共享内存实现零拷贝传输,解决这些问题。


Q: 支持 Android 版本?

A:

  • Android 10+ (API 29): 基本功能支持
  • Android 15: 需要 SELinux 策略配置

Q: 需要 Root 吗?

A: 不需要 Root,但需要:

  • 系统权限(logsystem 组)
  • SELinux 策略允许

如果是普通 App,只能作为消费者使用。


Q: 性能有多好?

A:

  • 写入延迟: < 1 μs
  • 端到端延迟: < 5 ms
  • 吞吐量: > 100,000 条/秒
  • CPU 占用: < 1%

部署问题

Q: 编译报错找不到 cutils/ashmem.h?

A: 确保在 AOSP 环境编译,或安装相应的 NDK 库。

# AOSP 编译
source build/envsetup.sh
lunch <target>
mma logcat_daemon

Q: 安装后启动失败?

A: 检查以下几点:

# 1. 检查权限
adb shell ls -la /system/bin/logcat_daemon

# 2. 检查 SELinux
adb shell getenforce

# 3. 查看日志
adb shell logcat -s logcat_daemon:V

# 4. 临时禁用 SELinux 测试
adb shell setenforce 0

Q: SELinux 报错怎么办?

A: 查看 SELinux 拒绝日志:

adb shell dmesg | grep avc | grep logcat_daemon

根据报错添加相应规则到 .te 文件。


使用问题

Q: 如何作为消费者使用?

A: 链接 liblog_consumer.so 并调用 API:

#include <log_consumer.h>

int main() {
    logdaemon::LogConsumer consumer;
    if (consumer.connect("/dev/socket/system_logs_v1")) {
        logdaemon::LogEntry entry;
        while (consumer.read(entry)) {
            // 处理日志
        }
    }
    return 0;
}

Q: 消费者提示 "Failed to connect"?

A: 检查:

# 1. Daemon 是否运行
adb shell ps -A | grep logcat_daemon

# 2. Socket 是否存在
adb shell ls -la /dev/socket/system_logs_v1

# 3. Socket 路径是否正确
# 默认: /dev/socket/system_logs_v1

Q: 日志有丢失怎么办?

A: 可能原因和解决:

  1. 缓冲区太小

    # 增大缓冲区
    logcat_daemon --size 8192
  2. 消费者处理太慢

    • 使用批量读取
    • 异步处理
    • 减少格式化开销
  3. 系统负载高

    • 检查 CPU 占用
    • 优化消费者逻辑

Q: 如何过滤日志?

A: 在消费者端过滤:

consumer.set_callback([](const logdaemon::LogEntry& entry) {
    // 按优先级过滤
    if (entry.priority < static_cast<uint8_t>(logdaemon::LogPriority::WARN)) {
        return;
    }
    
    // 按包名过滤
    if (strstr(entry.tag, "MyApp") == nullptr) {
        return;
    }
    
    // 处理
    std::cout << entry.message << std::endl;
});

Q: 多个消费者如何处理?

A: 每个消费者独立连接,各自维护读位置:

// 消费者 1
LogConsumer consumer1;
consumer1.connect("/dev/socket/system_logs_v1");

// 消费者 2
LogConsumer consumer2;
consumer2.connect("/dev/socket/system_logs_v1");

// 两者独立读取,互不影响

性能问题

Q: CPU 占用过高怎么办?

A:

  1. 禁用实时优先级

    logcat_daemon --no-realtime
  2. 检查消费者是否卡住

  3. 降低读取频率

    while (consumer.read(entry)) {
        usleep(10000);  // 10ms 间隔
    }

Q: 内存占用过大怎么办?

A: 减小缓冲区大小:

logcat_daemon --size 1024  # ~1.1 MB

Q: 延迟过高怎么办?

A: 检查:

  1. logd 缓冲区

    logcat -G 1M  # 减小 logd 缓冲区
  2. 消费者处理速度

    • 使用批量读取
    • 异步处理
  3. 系统负载

    • 检查其他进程 CPU 占用

技术问题

Q: 为什么不用 Binder?

A: Binder 适合 RPC,但对于高频日志传输:

  • 每次传输需要序列化/反序列化
  • 有系统调用开销
  • 大数据量时效率低

共享内存更适合高频大数据传输。


Q: 环形缓冲区如何避免数据竞争?

A: 使用无锁设计:

  • 写指针使用原子递增
  • 读指针独立维护
  • 不需要锁,仅内存屏障

Q: 如何保证数据一致性?

A:

  • 原子操作保证指针更新
  • 内存屏障保证写入顺序
  • 单生产者设计避免写入竞争

Q: 进程崩溃如何处理?

A:

  • Daemon 崩溃: 消费者 mmap 失效,需要重连
  • Consumer 崩溃: Daemon 无感知,新消费者从头开始

扩展问题

Q: 能否支持多生产者?

A: 当前设计是单生产者(daemon),多消费者。多生产者需要更复杂的无锁算法(如 MPMC 队列),会增加开销。


Q: 能否持久化到文件?

A: 在消费者端实现:

#include <fstream>

std::ofstream log_file("/data/logs/system.log");

consumer.set_callback([&log_file](const LogEntry& entry) {
    log_file << LogParser::format(entry) << std::endl;
});

Q: 能否发送到远程服务器?

A: 消费者端实现网络发送:

consumer.set_callback([](const LogEntry& entry) {
    // 通过 HTTP/gRPC 发送到服务器
    send_to_server(entry);
});

Q: 能否实时查看?

A: 使用示例消费者:

adb shell /system/bin/log_consumer_example

或自己实现 UI 展示。


其他问题

Q: 与 logcat 命令兼容吗?

A: 完全兼容。Daemon 只是读取 logd,不影响 logcat 命令使用。


Q: 会影响系统日志功能吗?

A: 不会。Daemon 只读取 logd,不修改任何系统行为。


Q: 开源协议是什么?

A: Apache License 2.0,可自由使用和修改。


Q: 如何贡献代码?

A:

  1. Fork 项目
  2. 创建功能分支
  3. 提交 Pull Request

请确保:

  • 代码风格一致
  • 添加单元测试
  • 更新相关文档

Q: 在哪里提问?

A:

  • GitHub Issues: 功能请求和 Bug 报告
  • 讨论区: 使用问题和技术讨论