Files
rust_raidguardx/GS_Rust_Refactoring_Analysis.md
T
2026-03-29 14:28:31 +08:00

10 KiB

GS (DtrGuiSrv) Rust 重構分析

概述

分析是否可將 GS (DtrGuiSrv) C 語言程式完整用 Rust 重構為 raidguard_x_gui_server

現有 GS 元件分析

GS (C) 元件清單

檔案 功能 複雜度 依賴
cMain.c 主程式入口、初始化 所有模組
cNetWork.c TCP 網路通訊 (Port 8922) socket API
cInBand.c In-Band API 處理 RAID Driver
cPollingEvent.c 事件輪詢執行緒 佇列、檔案
cMail.c Email 發送 (SMTP) SMTP library
cShareMem.c 共享記憶體 POSIX SHM
cSrvConfig.c 伺服器設定 檔案 I/O
cDTRIoCtl.c RAID I/O Control Driver API

每個元件的關鍵功能

cMain.c
├── InitGUIServer()          - 初始化
├── InitSMTP()              - SMTP 初始化
├── InitRAIDCard()          - RAID 卡初始化
└── Main Loop               - 網路監聽

cNetWork.c
├── InitialSrvSocket()      - 建立 TCP Server (Port 8922)
├── InitialClientSocket()   - accept()
├── GUITrans()              - TCP 傳輸 (Phase1 + Phase2)
└── ServerGUITrans()        - 伺服器端傳輸

cInBand.c
├── HandleInBandReq()       - 處理 In-Band 請求
├── HandleSrvConfigReq()   - 處理伺服器設定
└── [RAID Driver I/O]       - 與硬體通訊

cPollingEvent.c
├── PollingCtlrEvent()      - 執行緒:輪詢事件
├── SaveInBandEvent()       - 儲存到記憶體佇列
├── RecEventToFile()        - 寫入事件檔案
└── HandleInBandEventReq()  - 處理 GC 請求

cMail.c
├── InitMailEntryFreeQ()    - 初始化郵件佇列
├── IssueMailOut()          - 發送郵件
└── LoadMailAddrFromFile()  - 載入郵件地址

cShareMem.c
├── InitialSHMForAllCtlr() - 初始化共享記憶體
└── 與 RAID Driver 共享資料

cDTRIoCtl.c
├── QuaryDTR()              - 查詢 RAID 資訊
├── DevIoControl()          - I/O Control
└── 硬體驅動程式介面

重構可行性分析

可以重構的部分 ()

元件 Rust 方案 難度
TCP 網路 tokio, async-std
協議解析 nom, manual parsing
事件輪詢 tokio::spawn, interval
設定管理 serde_json, toml
日誌系統 tracing, log
Email 發送 lettre
錯誤處理 thiserror, anyhow

難以重構的部分 (⚠️)

元件 問題 建議
cShareMem.c POSIX 共享記憶體依賴 使用 rust-posix-shmem 或 FFI
cDTRIoCtl.c RAID Driver I/O 需要 FFI 綁定或重寫 Driver
硬體驅動 低層級硬體存取 保持 C 或用 FFI

需要 FFI 的部分

// 使用 FFI 呼叫現有 C 函數
#[repr(C)]
pub struct CtlrInfo {
    pub bStatus: u8,
    pub bCtlrSN: [c_char; 16],
    // ...
}

extern "C" {
    fn QuaryDTR(bDevNo: u8, bPageBuf: *mut u8, pbHeatsink: *mut u8) -> c_short;
    fn DevIoControl(...) -> c_uchar;
    fn GetCtlSemP(DeviceNum: c_short) -> c_short;
    fn GetCtlSemV(DeviceNum: c_short) -> c_short;
}

現有 Rust 專案結構

raidguard_x_gui_server/
├── Cargo.toml              # tokio, serde, tracing, lettre
├── src/
│   ├── main.rs            # 入口
│   ├── lib.rs             # library
│   ├── server.rs          # TCP Server
│   ├── protocol/          # 協議解析
│   ├── handlers/          # 請求處理
│   ├── mock/             # 模擬數據
│   └── backend/          # 後端

重構架構建議

模組化設計

raidguard_x_gui_server/
├── src/
│   ├── main.rs
│   ├── lib.rs
│   │
│   ├── network/          # 網路通訊
│   │   ├── mod.rs
│   │   ├── server.rs     # TCP Server (Port 8922)
│   │   ├── transport.rs  # Phase1/Phase2 傳輸
│   │   └── client.rs    # Client 連線管理
│   │
│   ├── protocol/         # 協議
│   │   ├── mod.rs
│   │   ├── request.rs   # 請求解析
│   │   ├── response.rs  # 回應封裝
│   │   └── error.rs    # 協議錯誤
│   │
│   ├── inband/          # In-Band API
│   │   ├── mod.rs
│   │   ├── handler.rs   # 請求處理
│   │   ├── page.rs      # Page 資料
│   │   └── password.rs  # 密碼處理
│   │
│   ├── event/           # 事件處理
│   │   ├── mod.rs
│   │   ├── queue.rs     # 事件佇列
│   │   ├── polling.rs   # 輪詢執行緒
│   │   └── storage.rs   # 事件儲存
│   │
│   ├── email/           # Email 通知
│   │   ├── mod.rs
│   │   ├── smtp.rs      # SMTP 發送
│   │   └── template.rs # 郵件範本
│   │
│   ├── config/          # 設定管理
│   │   ├── mod.rs
│   │   ├── server.rs    # 伺服器設定
│   │   └── storage.rs  # 設定儲存
│   │
│   ├── driver/          # RAID Driver (FFI)
│   │   ├── mod.rs
│   │   ├── ffi.rs       # FFI 綁定
│   │   └── types.rs     # C 類型包裝
│   │
│   └── logging/         # 日誌
│       └── mod.rs

技術選型

功能 Rust 選擇 說明
非同步 runtime tokio 完整 async/await 支援
TCP 網路 tokio::net 內建 TCP 支援
協議解析 nom / 手動 簡單協議,手動即可
序列化 serde JSON 支援
Email lettre SMTP client
日誌 tracing 結構化日誌
錯誤處理 thiserror 錯誤鏈
共享記憶體 libc::sys::shm FFI
執行緒安全 Arc<Mutex<>> 內建

重構階段規劃

Phase 1: 基礎設施 (1-2 週)

  • 專案初始化 (現有)
  • TCP Server (Port 8922)
  • 協議解析 (Phase1/Phase2)
  • 基本請求/回應處理
  • 日誌系統

Phase 2: In-Band API (2-3 週)

  • GET_PAGE 處理 (0x01)
  • SEND_PASSWORD 處理 (0x1D)
  • 其他 OpCode 處理
  • 與 RAID Driver FFI

Phase 3: 事件系統 (1-2 週)

  • 事件輪詢執行緒
  • 事件佇列
  • 事件儲存 (檔案)
  • GC 事件查詢

Phase 4: 通知系統 (1 週)

  • Email 發送 (SMTP)
  • SNMP Trap (可選)
  • 設定管理

Phase 5: 整合測試 (1-2 週)

  • 單元測試
  • 整合測試
  • 效能優化
  • 文檔

挑戰與解決方案

挑戰 1: RAID Driver I/O

問題: cDTRIoctl.c 需要與硬體驅動程式直接通訊

解決方案:

// 方案 A: FFI 呼叫現有 C 函數
#[link(name = "DtrIoCtl")]
extern "C" {
    fn DevIoControl(...) -> c_uchar;
}

// 方案 B: 將 Driver 程式碼移植到 Rust
// (需要大量時間)

// 方案 C: 保持 GS 為 C,只重構 GUI 部分
// (推薦: 混合架構)

挑戰 2: 共享記憶體

問題: cShareMem.c 使用 POSIX 共享記憶體

解決方案:

// 使用 nix crate
use nix::sys::shm::{shmat, shmget, ShmFlags};

// 或使用 libc
use libc::{shmget, shmat, shmctl, IPC_RMID};

挑戰 3: 執行緒同步

問題: C 的 Semaphore 需要轉換

解決方案:

// Rust 建議使用
use std::sync::{Mutex, Semaphore, Arc};

// 或使用 tokio::sync
use tokio::sync::{Mutex, Semaphore};

挑戰 4: 相容性

問題: 需要完全相容現有 GC (Java) 協議

解決方案:

// 確保位元組級別完全相同
#[repr(C)]
struct RequestHeader {
    pub req_type: u8,
    pub phase_code: u8,
    pub length: u16,  // Little-endian
}

// 測試覆蓋所有現有功能

推薦策略

策略 A: 完全重構 (全部 Rust)

優點:

  • 單一語言,維護簡單
  • 記憶體安全
  • 現代化生態

缺點:

  • 需要 FFI 或重寫 Driver
  • 開發時間長

時間預估: 3-4 個月

策略 B: 混合架構 (推薦)

┌─────────────────────────────────────────────────────────────┐
│                    混合架構                                    │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌─────────────┐    ┌─────────────┐    ┌─────────────┐   │
│  │  GC (Java)  │    │ Rust Server │    │  C Driver  │   │
│  │   Port 8922 │◄──►│             │◄──►│   (現有)   │   │
│  │             │    │             │    │             │   │
│  └─────────────┘    └──────┬──────┘    └─────────────┘   │
│                            │                                │
│                     共享記憶體/FDI                          │
│                                                              │
└─────────────────────────────────────────────────────────────┘

優點:

  • 保留穩定的 C Driver
  • Rust 處理網路/業務邏輯
  • 逐步遷移

缺點:

  • FFI 複雜度

時間預估: 2-3 個月

策略 C: 只重構 GUI Client

維持 GS 為 C 程式,只重構 GC (Java) 為 Rust GUI Client。

結論

可以完整重構,但建議採用混合策略:

  1. 網路/協議/事件/Email → Rust (可完全重構)
  2. RAID Driver/共享記憶體 → 保持 C 或 FFI
  3. 優先順序: 先重構 GC (Java→Rust) → 再考慮 GS

主要原因:

  • Driver 層變動風險高
  • GS 相對穩定,需求變化少
  • GC (GUI) 更有現代化價值

現有程式碼利用率

 raidguard_x_gui_server (現有)
 ├── ✅ network/server.rs     → 可基於 cNetWork.c
 ├── ✅ protocol/             → 可基於 GS 協議
 ├── ⚠️  handlers/            → 需要實作 In-Band API
 └── ❌ backend/              → 需要連接 RAID Driver

下一步建議

  1. 短期: 完成現有 Rust Server 與 GS 的替換
  2. 中期: FFI 整合現有 C Driver
  3. 長期: 逐步將 Driver 移植到 Rust (如有需要)