Windows 上的 DTrace

DTrace (DTrace.exe) 是顯示系統資訊和事件的命令行工具。 DTrace 是移植到視窗的 開放原始碼 追蹤平臺。 DTrace 最初是針對 Solaris 操作系統所開發。 它提供這兩個使用者/核心函式的動態檢測,其能夠使用 D 語言的推測追蹤編寫腳本。 此外,DTrace 具有 Windows OS 特定的擴充功能,例如 ETW 檢測、ETW 事件產生、系統呼叫探查和實時傾印擷取功能。

注意

在 18980 版和 Windows Server 組建 18975 之後,Windows 測試人員組建支援 DTrace。

Windows GitHub 網站上的 DTrace 位於:

https://github.com/microsoft/DTrace-on-Windows

開啟 DTrace 資訊

如需 DTrace 的詳細資訊,請參閱 劍橋大學的 OpenDTrace 規格 1.0 版。

主要 GitHub 網站位於 https://github.com/opendtrace/

有一組實用的腳本可在取得 https://github.com/opendtrace/toolkit

有許多 DTrace 書籍可供使用,例如:

DTrace:布蘭登·格雷格和吉姆·莫羅在 Oracle Solaris、Mac OS X 和 FreeBSD 中的動態追蹤

Solaris 效能與工具:DTrace 和 MDB 技術 for Solaris 10 和 OpenSolaris by Richard McDougall、Jim Mauro 和 Brendan Gregg

提供 Windows DTrace 的意見反應

使用意見反應中樞來要求新功能,或使用 Windows DTrace 回報任何問題或 Bug。

  1. 啟動意見反應中樞。 移至搜尋,輸入意見反應一詞,然後選取 [意見反應中樞]。
  2. 選取 [ 建議功能 ] 或 [回報問題]。
  3. 提供問題或建議的詳細特定描述。

DTrace Windows 延伸模組

以下是 Windows 上提供的一些提供者,以及其檢測內容。

  • syscall – NTOS 系統呼叫

  • fbt (函式界限追蹤) - 核心函式專案和傳回

  • pid (行程識別子) - 使用者模式進程追蹤。 如同內核模式 FBT,但也允許檢測任意函式位移。

  • etw (Windows 事件追蹤) – 允許針對 ETW 定義探查此提供者有助於利用 DTrace 中現有的作業系統檢測。

SYSCALL

SYSCALL 會為每個系統呼叫提供一組探查:輸入探查,會在系統呼叫進入之前引發,並在系統呼叫完成之後引發,但在控制權轉移回用戶層級之前引發的傳回探查。 針對所有 SYSCALL 探查,函式名稱會設定為已檢測系統呼叫的名稱,而模組名稱是函式所在的模組。 從命令提示字元輸入 命令 dtrace.exe -l -P syscall ,即可找到 SYSCALL 提供者所提供的系統呼叫名稱。 請注意,探查名稱為小寫 syscall。 此命令 dtrace -ln syscall::: 也會列出 syscall 提供者提供的所有探查及其參數。

C:\> dtrace -ln syscall:::
  ID   PROVIDER            MODULE                          FUNCTION NAME
    6    syscall                                 NtWaitHighEventPair entry
    7    syscall                                 NtWaitHighEventPair return
    8    syscall                       NtRegisterThreadTerminatePort entry
    9    syscall                       NtRegisterThreadTerminatePort return
...

請注意,並非所有螢幕輸出都會顯示在這些範例中。 "..."用來表示截斷的輸出。

若要卷動輸出,請透過管道向外傳送至 更多 命令,如下所示:

dtrace -ln syscall:::|more

新增 v 選項,以顯示可用 syscall 探查的詳細資訊。

C:\> dtrace -lvn syscall:::
...

  942    syscall                                    NtSaveMergedKeys entry

        Probe Description Attributes
                Identifier Names: Private
                Data Semantics:   Private
                Dependency Class: ISA

        Argument Attributes
                Identifier Names: Private
                Data Semantics:   Private
                Dependency Class: ISA

        Argument Types
                args[0]: HANDLE
                args[1]: HANDLE
                args[2]: HANDLE
...

ETW

DTrace 包含現有指令清單/追蹤記錄 ETW 探查的支援。 您可以在引發事件時同步檢測、篩選和剖析 ETW 事件。 此外,DTrace 可以用來合併各種事件/系統狀態,以提供合併的輸出數據流,以協助偵錯複雜的錯誤狀況。

此命令 dtrace -ln etw::: 會列出 syscall 提供者提供的所有探查及其參數。

  C:\> dtrace -ln etw:::
  ID   PROVIDER            MODULE                          FUNCTION NAME
  944        etw 048dc470-37c1-52a8-565a-54cb27be37ec           0xff_0xffffffffffffffff generic_event
  945        etw aab97afe-deaf-5882-1e3b-d7210f059dc1           0xff_0xffffffffffffffff generic_event
  946        etw b0f40491-9ea6-5fd5-ccb1-0ec63be8b674           0xff_0xffffffffffffffff generic_event
  947        etw 4ee869fa-9954-4b90-9a62-308c74f99d32           0xff_0xffffffffffffffff generic_event
  ...

如需詳細資訊,請參閱 DTrace ETW

函式界限追蹤 (FBT)

函式界限追蹤 (FBT) 提供者會提供與 Windows 核心中大部分函式專案相關聯的探查和傳回。 函式是程式文字的基本單位。 與其他 DTrace 提供者類似,FBT 在未明確啟用時沒有探查效果。 啟用時,FBT 只會在探查函式中引發探查效果。 FBT 已在 x86 和 x64 平台上實作。

針對每個指令集,有幾個函式不會呼叫其他函式,而且由編譯程式(所謂的分葉函式)高度優化,無法由 FBT 檢測。 這些函式的探查不存在於 DTrace 中。

此命令 dtrace -ln fbt:nt:: 會列出 nt 模組可用的所有探查及其參數。 使用除錯程式 lm (List Loaded Modules) 命令來列出所有可用的模組。

C:\>dtrace -ln "fbt:nt::"
   ID   PROVIDER            MODULE                          FUNCTION NAME
 3336        fbt                nt                PiDqActionDataFree entry
 3337        fbt                nt                PiDqActionDataFree return
 3338        fbt                nt PiDqActionDataGetRequestedProperties entry
 3339        fbt                nt PiDqActionDataGetRequestedProperties return
 3340        fbt                nt _CmGetMatchingFilteredDeviceInterfaceList entry
...

注意

由於 nt 中有數千個可用的呼叫,因此在執行記錄數據的 DTrace 命令時,讓函式名稱保持空白並不是個好主意。 避免可能效能影響的建議方法是至少指定函式名稱的一部分,例如 fbt:nt:*Timer*:entry

PID

DTrace PID 提供者可讓您追蹤使用者模式進程的內部執行,例如網頁瀏覽器或資料庫。 您也可以在進程啟動時附加 DTrace,以便偵錯進程啟動問題。 在 PID 定義中,您可以指定函式中定義的函式,以及函式內的特定位移(或所有使用通配符 *) 的位移。 PID 提供者需要在腳本執行時啟動或執行二進位檔。

這個範例命令會顯示與notepad.exe相關聯之 PID 中特定呼叫的相關信息。 使用除錯程式 lm (List Loaded Modules) 命令來列出所有可用的模組。

C:\Windows\system32>dtrace -ln "pid$target:ntdll:RtlAllocateHeap:entry" -c notepad.exe
   ID   PROVIDER            MODULE                          FUNCTION NAME
 5102    pid6100             ntdll                   RtlAllocateHeap entry

注意

以 C++ 撰寫的追蹤函式時,函式名稱可能太長或裝飾,無法指定為具有完整格式的探查。 常見的解決方案是使用唯一符合目標函式的表達式。 例如,使用 『String??複製' 做為探查名稱的 'probefunc' 部分,以符合 'String::Copy()' 或 '*GetPinnableReference' 以符合 'String::GetPinnableReference()'。

DTrace Windows 架構

使用者透過 DTrace 命令與 DTrace 互動,該命令可作為 DTrace 引擎的前端。 D 腳本會在使用者空間中編譯成中繼格式 (DIF),並傳送至 DTrace 核心元件以執行,有時稱為 DIF 虛擬機。 這會在dtrace.sys驅動程序中執行。

Traceext.sys (追蹤延伸模組) 是 Windows 核心延伸模塊驅動程式,可讓 Windows 公開 DTrace 依賴的功能以提供追蹤。 Windows 核心會在 stackwalk 或記憶體存取期間提供圖說文字,然後由追蹤延伸模組實作。

此圖顯示連線至 libtrace 的 DTrace Windows 架構,其中dtrace.exe會與DTrace.sys通訊,以及呼叫Traceext.sys。

在 Windows 下安裝 DTrace

  1. 確認您正在執行支援的 Windows 版本。 在 18980 版和 Windows Server 組建 18975 之後,測試人員組建 20H1 Windows 支援目前的 DTrace 下載。 在舊版 Windows 上安裝此版本的 DTrace 可能會導致系統不穩定,不建議這麼做。 (19H1 的 DTrace 封存版本已無法使用,不再支援。

  2. 從 Microsoft 下載中心下載 MSI 安裝檔案 (下載 Windows 上的 DTrace)。

  3. 選取 [完成安裝]。

    重要

    使用 bcdedit 變更開機資訊之前,您可能需要暫時暫停測試計算機上的 Patchguard、BitLocker 和安全開機等 Windows 安全性功能。 在測試完成時重新啟用這些安全性功能,並在停用安全性功能時適當地管理測試計算機。

  4. 更新 PATH 環境變數以包含 C:\Program Files\DTrace

set PATH=%PATH%;"C:\Program Files\DTrace"
  1. 使用 bcdedit 命令在機器上啟用 DTrace。
bcdedit /set dtrace ON

當您更新至新的 Windows 測試人員組建時,您必須再次設定 dtrace bcdedit 選項。

注意

如果您使用 BitLocker,請在變更開機值時將其停用。 如果您未這麼做,系統可能會提示您輸入 BitLocker 修復金鑰。 從這種情況中復原的其中一種方法是開機至復原控制台,並還原 bcdedit 值 。 bcdedit /set {default} dtrace on 如果 OS 更新已移除值,而且您已將它新增至 ,則若要復原 OS,請使用 bcdedit 來移除值 bcdedit /deletevalue {default} dtrace。 然後停用 BitLocker 並重新啟用 dtrace, bcdedit /set dtrace ON

將 「HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\EnableVirtualizationBasedSecurity」 設定為 1,以啟用 VSM 和安全核心,在機器上設定 VSM(虛擬安全模式)來啟用核心函式界限追蹤 (FBT)。

若要這樣做,請使用 REG Add 命令,如下所示:

REG ADD HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\DeviceGuard\ /v EnableVirtualizationBasedSecurity /t REG_DWORD /d 1

某些 DTrace 命令使用 Windows 符號。 若要使用 Windows 符號建立符號目錄,並設定符號路徑:

mkdir c:\symbols
set _NT_SYMBOL_PATH=srv*C:\symbols*https://msdl.microsoft.com/download/symbols

如需符號路徑的詳細資訊,請參閱 Windows 調試程式的符號路徑。

在虛擬機內使用 DTrace

如果在 VM 上執行 DTrace,請使用下列 PowerShell 命令,在支援 VM 的機器上開啟巢狀虛擬化。 <VMName>提供您執行 DTrace 之 VM 的 。 以 管理員 istrator 開啟 PowerShell Windows。

Set-VMProcessor -VMName <VMName> -ExposeVirtualizationExtensions $true

重新啟動支援 VM 的電腦。

驗證 DTrace 安裝

使用 -l 選項來列出使用中的探查。 如果 DTrace 為作用中,則應該針對 etw 和系統事件列出許多探查。

以系統管理員身分開啟 Windows 命令提示字元,以輸入 DTrace 命令。

C:\> dtrace -l

...

  179    syscall                                 NtLockVirtualMemory return
  180    syscall                               NtDeviceIoControlFile entry
  181    syscall                               NtDeviceIoControlFile return
  182    syscall                                 NtCreateUserProcess entry
  183    syscall                                 NtCreateUserProcess return
  184    syscall                                      NtQuerySection entry
  185    syscall                                      NtQuerySection return

...

 3161        etw 222962ab-6180-4b88-a825-346b75f2a24a           0xff_0xffffffffffffffff generic_event
 3162        etw 3ac66736-cc59-4cff-8115-8df50e39816b           0xff_0xffffffffffffffff generic_event
 3163        etw 42695762-ea50-497a-9068-5cbbb35e0b95           0xff_0xffffffffffffffff generic_event
 3164        etw 3beef58a-6e0f-445d-b2a4-37ab737bd47e           0xff_0xffffffffffffffff generic_event

...

如果只列出這三個探查,載入DTrace.sys驅動程式就會發生問題。

C:\>  dtrace -l
   ID   PROVIDER            MODULE                          FUNCTION NAME
    1     dtrace                                                     BEGIN
    2     dtrace                                                     END
    3     dtrace                                                     ERROR

開始使用 DTrace - 一行命令

從系統管理員命令提示字元執行這些命令以開始使用。

此命令會依程序顯示5秒的 syscall 摘要。 tick-5sec 參數會指定時間週期。 exit(0):會導致命令在完成時結束,回到命令提示字元。 使用 指定輸出 [pid,execname] = count(); 時,會顯示進程標識碼 (PID)、可執行檔名稱,以及過去 5 秒的計數。

C:\> dtrace -Fn "tick-5sec {exit(0);} syscall:::entry{ @num[pid,execname] = count();} "  
dtrace: description 'tick-5sec ' matched 471 probes
CPU FUNCTION
  0 | :tick-5sec

     1792  svchost.exe                                                       4
     4684  explorer.exe                                                      4
     4916  dllhost.exe                                                       4
     6192  svchost.exe                                                       4
     6644  SecurityHealth                                                    4
       92  TrustedInstall                                                    5
      504  csrss.exe                                                         5
      696  svchost.exe                                                       6
...

此指令摘要說明定時器集/取消呼叫 3 秒:

C:\> dtrace -Fn "tick-3sec {exit(0);} syscall::Nt*Timer*:entry { @[probefunc, execname, pid] = count();}"
dtrace: description 'tick-3sec ' matched 14 probes
CPU FUNCTION
  0 | :tick-3sec

  NtCreateTimer                                       WmiPrvSE.exe                                            948                1
  NtCreateTimer                                       svchost.exe                                             564                1
  NtCreateTimer                                       svchost.exe                                            1276                1
  NtSetTimer2                                         svchost.exe                                            1076                1
  NtSetTimer2                                         svchost.exe                                            7080                1
  NtSetTimerEx                                        WmiPrvSE.exe                                            948                1
...  

使用符號的一行命令

這些命令會利用 Windows 符號,並要求將符號路徑設定為安裝一節中所述。 如先前安裝所述,請建立目錄,並使用這些命令來設定符號路徑。

C:\> mkdir c:\symbols
C:\> set _NT_SYMBOL_PATH=srv*C:\symbols*https://msdl.microsoft.com/download/symbols

這個範例命令會顯示頂端NT函式。

C:\> dtrace -n "fbt:nt:*Timer*:entry { @k[probefunc] = count(); } tick-5s { trunc(@k, 10);printa(@k); exit(0); }"
dtrace: description 'fbt:nt:*Timer*:entry ' matched 340 probes
CPU     ID                    FUNCTION:NAME
  0  22362                         :tick-5s
  KeCancelTimer                                                   712
  KeSetTimer2                                                     714
  HalpTimerClearProblem                                           908
  ExpSetTimerObject                                               935
  NtSetTimerEx                                                    935
  KeSetTimer                                                     1139
  KeSetCoalescableTimer                                          3159
  KeResumeClockTimerFromIdle                                    11767
  xHalTimerOnlyClockInterruptPending                            22819
  xHalTimerQueryAndResetRtcErrors                               22819

此命令會傾印 SystemProcess 核心結構。

C:\> dtrace -n "BEGIN {print(*(struct nt`_EPROCESS *) nt`PsInitialSystemProcess);exit(0);}"

...

   uint64_t ParentSecurityDomain = 0
    void *CoverageSamplerContext = 0
    void *MmHotPatchContext = 0
    union _PS_PROCESS_CONCURRENCY_COUNT ExpectedConcurrencyCount = {
         Fraction :20 = 0
         Count :12 = 0
        uint32_t AllFields = 0
    }
    struct _KAFFINITY_EX IdealProcessorSets = {
        uint16_t Count = 0x1
        uint16_t Size = 0x20
        uint32_t Reserved = 0
        uint64_t [32] Bitmap = [ 0x1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
    }
}

此命令會顯示過去 10 秒的最上層核心堆疊。

C:\> dtrace -qn "profile-997hz { @[stack()] = count(); } tick-10sec { trunc(@,5); printa(@); exit(0);}"

              nt`KiDispatchInterruptContinue
              nt`KiDpcInterrupt+0x318
              nt`KiSwapThread+0x1054
              nt`KiCommitThreadWait+0x153
              nt`KeRemoveQueueEx+0x263
              nt`IoRemoveIoCompletion+0x54
              nt`NtWaitForWorkViaWorkerFactory+0x284
              nt`KiSystemServiceCopyEnd+0x35
               14

              nt`KiDispatchInterruptContinue
              nt`KiDpcInterrupt+0x318
...

此命令會顯示啟動期間notepad.exe所叫用的最上層模組。 -c 選項會執行指定的命令(notepad.exe),並在完成時結束。

C:\> dtrace -qn "pid$target:::entry { @k[probemod] = count();} tick-10s{printa(@k); exit(0);}" -c notepad.exe

  gdi32full                                                         5
  msvcp_win                                                         6
  combase                                                           7
  notepad                                                           9
  ADVAPI32                                                         10
  GDI32                                                            11
  SHELL32                                                          11
  USER32                                                           21
  win32u                                                          345
  KERNELBASE                                                     3727
  msvcrt                                                         7749
  KERNEL32                                                       9883
  RPCRT4                                                        11710
  ntdll                                                        383445

另請參閱

DTrace Windows 程式設計

DTrace ETW

DTrace Live Dump

DTrace Windows 程式代碼範例