# 守护进程与主应用关系说明 ## 📋 概述 `soft_bus` (主应用) 和 `soft_bus_daemon` (守护进程) 是两个**独立的进程**,它们通过 **D-Bus** 进行通信,并共享同一个数据库文件。 ## 🏗️ 架构图 ``` ┌─────────────────────────────────────────────────────────────┐ │ 系统架构 │ └─────────────────────────────────────────────────────────────┘ ┌──────────────────────┐ D-Bus ┌──────────────────────┐ │ soft_bus │ ◄─────────────────────► │ soft_bus_daemon │ │ (主应用进程) │ (进程间通信) │ (守护进程) │ │ │ │ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │ │ CoreService │ │ │ │ CoreService │ │ │ │ (进程内单例) │ │ │ │ (进程内单例) │ │ │ └────────────────┘ │ │ └────────────────┘ │ │ │ │ │ │ │ │ ▼ │ │ ▼ │ │ ┌────────────────┐ │ │ ┌────────────────┐ │ │ │ DeviceBusCore │ │ │ │ DeviceBusCore │ │ │ │ SoftBusCore │ │ │ │ SoftBusCore │ │ │ └────────────────┘ │ │ └────────────────┘ │ │ │ │ │ │ │ └─────────┼────────────┘ └─────────┼────────────┘ │ │ │ ┌──────────────────┐ │ └─────────────►│ soft_bus_db │◄───────────┘ │ (SQLite数据库) │ └──────────────────┘ (共享数据库文件) ``` ## 🔍 详细说明 ### 1. 进程独立性 #### soft_bus (主应用) - **文件**: `main.cpp` - **类型**: GUI 应用程序 (QApplication) - **功能**: - 提供用户界面 - 管理设备配置 - 显示数据可视化 - 通过 DaemonClient 查询守护进程状态 #### soft_bus_daemon (守护进程) - **文件**: `daemon_main.cpp` - **类型**: 后台服务进程 (QCoreApplication) - **功能**: - 独立运行的核心服务 - 通过 D-Bus 提供状态查询接口 - 管理设备总线和消息路由 - 即使主应用关闭也能继续运行 ### 2. 核心服务实例 每个进程都有**自己独立**的 `CoreService` 实例: ```cpp // 主应用进程 (main.cpp) CoreService* coreService = CoreService::instance(); // 进程1的实例 coreService->initialize(); // 初始化进程1的核心 // 守护进程 (daemon_main.cpp) CoreService* coreService = CoreService::instance(); // 进程2的实例 coreService->initialize(); // 初始化进程2的核心 ``` **重要**: `CoreService::instance()` 是**进程内单例**,不是跨进程单例。两个进程各自有独立的内存空间。 ### 3. 数据库共享 两个进程都使用**同一个 SQLite 数据库文件** `soft_bus_db`: ```cpp // 两个进程都调用 m_deviceBusCore->initDB(QStringLiteral("soft_bus_db")); ``` **效果**: - ✅ 数据持久化共享(设备注册、消息存储等) - ✅ SQLite 自动处理并发访问 - ❌ 内存状态不共享(每个进程的设备列表缓存独立) ### 4. D-Bus 通信 主应用通过 `DaemonClient` 与守护进程通信: ```cpp // 主应用 (mainwindow.cpp) DaemonClient* client = new DaemonClient(this); client->connectToDaemon(); // 连接到守护进程 client->getStatus(); // 查询守护进程状态 client->getDeviceCount(); // 获取设备数量 ``` 守护进程通过 `DaemonService` 提供 D-Bus 接口: ```cpp // 守护进程 (daemon_main.cpp) DaemonService* service = new DaemonService(coreService, &app); connection.registerService("com.softbus.Daemon"); // 注册 D-Bus 服务 connection.registerObject("/com/softbus/Daemon", service); // 注册对象 ``` **D-Bus 接口**: - `isRunning()` - 检查守护进程是否运行 - `getStatus()` - 获取状态信息(JSON) - `getLoadInfo()` - 获取负载信息(CPU、内存、消息速率) - `getDeviceCount()` - 获取设备数量 - `getMessageStats()` - 获取消息统计 - `getPid()` - 获取进程ID - `shutdown()` - 关闭守护进程 ### 5. 实际运行场景 #### 场景1: 只运行主应用 ``` soft_bus (进程1) └─ CoreService (实例1) └─ DeviceBusCore (实例1) └─ 连接 soft_bus_db ``` - 主应用独立运行 - 有自己的核心服务 - 可以正常工作 #### 场景2: 主应用 + 守护进程 ``` soft_bus (进程1) soft_bus_daemon (进程2) └─ CoreService (实例1) └─ CoreService (实例2) └─ DeviceBusCore (实例1) └─ DeviceBusCore (实例2) └─ 连接 soft_bus_db └─ 连接 soft_bus_db ▲ │ └────────── 共享数据库 ─────────┘ D-Bus 通信 ◄─────────► ``` - 两个进程同时运行 - 各自有独立的核心服务 - 共享数据库文件 - 通过 D-Bus 通信 #### 场景3: 主应用关闭,守护进程继续运行 ``` soft_bus (已关闭) soft_bus_daemon (进程2,继续运行) └─ CoreService (实例2) └─ DeviceBusCore (实例2) └─ 连接 soft_bus_db ``` - 守护进程独立运行 - 核心服务继续工作 - 数据继续写入数据库 ## 🔄 数据同步 ### 数据库层面(自动同步) - 设备注册信息 - 消息存储 - 设备状态(通过数据库查询) ### 内存层面(需要 D-Bus 查询) - 实时设备列表(每个进程独立缓存) - 运行时状态(需要通过 D-Bus 查询守护进程) ## 💡 设计意图 1. **守护进程**: 提供独立的后台服务,即使没有 GUI 也能运行 2. **主应用**: 提供用户界面,可以查询守护进程状态 3. **数据库共享**: 确保数据一致性 4. **进程隔离**: 提高稳定性,一个进程崩溃不影响另一个 ## ⚠️ 注意事项 1. **不是同一个核心**: 两个进程有独立的核心实例 2. **数据库共享**: 数据通过数据库共享,但内存状态独立 3. **D-Bus 通信**: 主应用通过 D-Bus 查询守护进程状态 4. **并发访问**: SQLite 自动处理多进程并发访问 ## 📝 总结 | 特性 | 说明 | |------|------| | **进程关系** | 两个独立的进程 | | **核心实例** | 各自有独立的 CoreService 实例 | | **数据库** | 共享同一个 SQLite 数据库文件 | | **通信方式** | 通过 D-Bus 进行进程间通信 | | **内存状态** | 各自独立,不共享 | | **数据持久化** | 通过数据库共享 | **简单理解**: - 它们像两个独立的"办公室",各自有自己的"工作空间"(内存) - 但共享同一个"文件柜"(数据库) - 通过"电话"(D-Bus)互相联系