首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

驅動層與應用層共用程式碼:雙目標編譯 SOURCES 檔案配置指南

     編輯:關於C語言

在 Windows 驅動開發中,將策略性、演算法類的核心邏輯同時編譯為核心模式庫(.lib/.sys)與使用者模式 DLL,可大幅提升開發測試效率。本文詳細說明如何透過 SOURCES 與 .def 檔案實現雙目標編譯。

核心策略:條件編譯宏切換目標類型

關鍵在於定義 KERNEL_BUILD 巨集:

  • 定義 KERNEL_BUILD:編譯為核心模式匯出驅動程式庫(TARGETTYPE=EXPORT_DRIVER),產出 .sys 與 .lib。
  • 未定義 KERNEL_BUILD:編譯為使用者模式動態連結庫(TARGETTYPE=DYNLINK),產出 .dll 與 .lib,並連結 CRT(USE_MSVCRT=1)。

SOURCES 檔案完整範例

# 核心開關:定義為 1 時編譯核心庫,註解掉則編譯使用者 DLL
KERNEL_BUILD=1

TARGETNAME=Sample
DLLDEF=Sample.def              # 匯出函數定義檔
TARGETPATH=../../bin           # .sys 或 .dll 輸出目錄
TARGETPATHLIB=../../lib        # .lib 輸出目錄

!ifdef KERNEL_BUILD
# === 核心模式編譯設定 ===
TARGETTYPE=EXPORT_DRIVER
!else
# === 使用者模式編譯設定 ===
TARGETTYPE=DYNLINK
USE_MSVCRT=1
DLLENTRY=_DllMainCRTStartup    # DLL 進入點
INCLUDES=$(INCLUDES); $(DDK_INC_PATH)
INCLUDES=$(INCLUDES); $(SDK_INC_PATH)
TARGETLIBS=$(TARGETLIBS) $(SDK_LIB_PATH)\kernel32.lib
TARGETLIBS=$(TARGETLIBS) $(SDK_LIB_PATH)\gdi32.lib
TARGETLIBS=$(TARGETLIBS) $(SDK_LIB_PATH)\advapi32.lib
TARGETLIBS=$(TARGETLIBS) $(SDK_LIB_PATH)\ntdll.lib
!endif

# === 共用專案頭文件路徑 ===
INCLUDES=$(INCLUDES); ../../inc
INCLUDES=$(INCLUDES); ../../inc/SampleOne
INCLUDES=$(INCLUDES); ../../inc/SampleTwo

# === 共用原始碼檔案 ===
SOURCES=\
    A.cpp\
    B.cpp\
    C.cpp\
    D.cpp

模組定義檔

; Sample.def
NAME "Sample.sys"          ; 核心庫名稱;若編譯 DLL 請改為 "Sample.dll"
EXPORTS
    DllInitialize PRIVATE  ; 核心庫初始化/卸載進入點(私有)
    DllUnload PRIVATE
    AFunc                  ; 共用對外介面函數
    BBFunc

共用程式碼進入點設計

核心庫需提供 DriverEntry/DriverUnload,內部委派給共用的 DllInitialize/DllUnload:

#include "ntddk.h"

extern "C" {
    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pusRegPath);
    void DriverUnload(PDRIVER_OBJECT pDriverObject);
    NTSTATUS DllInitialize(PUNICODE_STRING RegistryPath);
    NTSTATUS DllUnload();
}

void DriverUnload(PDRIVER_OBJECT pDriverObject) {
    DllUnload();
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pusRegPath) {
    DllInitialize(pusRegPath);
    pDriverObject->DriverUnload = DriverUnload;
    return STATUS_SUCCESS;
}

// 共用初始化/清理邏輯
NTSTATUS DllInitialize(PUNICODE_STRING RegistryPath) {
    DbgPrint("Sample: DllInitialize(%wZ)\n", RegistryPath);
    return STATUS_SUCCESS;
}

NTSTATUS DllUnload() {
    DbgPrint("Sample: DllUnload\n");
    return STATUS_SUCCESS;
}

// 共用函數:明確指定呼叫慣例避免連結錯誤
// DDK 預設 _stdcall,VC 預設 _cdecl
ULONG _stdcall TestFun(void) {
    return 100;
}

關鍵注意事項

  1. 呼叫慣例一致性:核心/使用者模式預設呼叫慣例不同,跨模組介面函數務必顯式指定 _stdcall。
  2. 頭文件隔離:共用程式碼不可直接包含 ntddk.h 等核心專用頭文件,需以條件編譯隔離。
  3. 測試優勢:使用者模式 DLL 可在 Visual Studio 直接偵錯,驗證演算法邏輯後再部署至核心,大幅縮短開發週期。

完整範例程式碼可參考:下載連結

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved