在 Windows 平台使用 TDM-GCC (MinGW) 開發動態鏈接庫 (DLL) 時,線程同步與庫的初始化/終止化是兩大核心挑戰。本文記錄從 Windows Critical Section 失效,到採用 pthread 互斥鎖成功運行,並利用 GCC 構造/析構屬性實現跨平台初始化的完整實踐過程。
理論上可用 Windows API 實現同步:
InitializeCriticalSection / DeleteCriticalSectionEnterCriticalSection / LeaveCriticalSection實測結果: 導致 DLL 載入失敗,具體原因未明(推測與 MinGW 運行時環境衝突有關)。
改用 POSIX 線程庫提供的互斥鎖:
pthread_mutex_init / pthread_mutex_destroypthread_mutex_lock / pthread_mutex_unlock編譯鏈接時添加 -lpthread 參數,預綁定 pthread 動態庫。實測 DLL 運行良好。
通過 objdump 分析生成的 DLL 發現:使用 pthread 互斥鎖時,DLL 並未真正引用 pthread 庫及相關函數符號。這強烈暗示 pthread-w32 實現層內部封裝了 Windows 原生同步原語(如 Slim Reader/Writer Locks 或 WaitOnAddress 等現代同步機制),而非簡單包裝 Critical Section。
Windows DLL 通常使用 DllMain 處理進程/線程掛載卸載事件,但這導致代碼平台耦合。GCC 提供構造/析構函數屬性,可實現源代碼級跨平台。
// 全局互斥鎖變量
pthread_mutex_t _ptm_mutex;
// 動態庫載入時自動調用
void __attribute__((constructor)) dynamic_library_init() {
pthread_mutex_init(&_ptm_mutex, NULL);
printf("dll _init() called OK\n");
}
// 動態庫卸載時自動調用
void __attribute__((destructor)) dynamic_library_fini() {
pthread_mutex_destroy(&_ptm_mutex);
printf("dll _fini() called OK\n");
}
__attribute__((constructor)):標記函數在共享庫載入時自動執行(優先於 DllMain 的 DLL_PROCESS_ATTACH)__attribute__((destructor)):標記函數在共享庫卸載時自動執行dynamic_library_init),避免與 GCC 內部保留的 _init/_fini 衝突-lpthread 需放在依賴它的庫之後objdump -T your.dll 確認無異常未定義符號這套方案已在生產環境驗證穩定,為 MinGW 開發 Windows DLL 提供了可靠的同步與生命週期管理基礎設施。