# FreeBSD DTrace 基礎了解


## 背景

可以知道的相關背景知識

### 歷史

最早在 Sun 裡面使用，後來移植到不同作業統，後來在 illumos 上面也有，在 Windows 也有。OpenDTrace 專案於 2016 年 9 月在GitHub上啟動，專案提供了程式碼和系統內部機制的完整文件。

Brendan Gregg 是澳洲系統效能工程師與開放原始碼開發者，以發明「火焰圖（Flame Graph）」而聞名。他是電腦系統觀測性與效能分析領域的領軍人物，著作廣受產業與學術界引用。2026 年起任職於 OpenAI，負責優化 ChatGPT 的資料中心效能。

Brendan 創建了多個 DTrace script 範本，DTrace 書籍就是他寫的。

### 事件

在 Track 系統中，我們可以看到不同事件

* 硬體事件，使用硬體計數器 (PMC/PMU)，用來分析效能像是：
  * FreeBSD pmcstat
  * Linux 的 perf
* 偵測 Kernel 的函式，可以用靜態或者動態的 probe，像是：
  * FreeBSD 的 DTrace
  * FreeBSD truss 追蹤 syscall
  * FreeBSD ktrace 為特定 process 開啟核心 log
  * Linux strace 追蹤 syscall，使用傳統 ptrace syscall
  * Linux ftrace，追蹤核心函式，背後使用 Linux kprobe
  * Linux uprobes 追蹤使用者函式
  * Linux eBPF，Linux 的 DTrace

靜態事件就是真的一開始編譯就編譯進去，動態事件就是動態添加的，像是函式的進入 and 返回。

比起傳統 ptrace 用一個 process 追蹤，其他損失效能比較小。

## DTrace

通常 DTrace 追蹤 Kernel 的一些 static probe，也提供動態 probe，也有提供在 userspace 的 static probe，例如有套件包含一個 DTrace 選項，用於啟用靜態偵測器在這些使用者套件上面。

預設有開啟 DTrace，要確認相關的 `dtraceall` 核心模組有被載入。

```shell
$ dtrace -l | more
49840        fbt            kernel          ufs_getacl_nfs4_internal return
49841        fbt            kernel                        ufs_getacl entry
49842        fbt            kernel                        ufs_getacl return
49843        fbt            kernel          ufs_setacl_nfs4_internal entry
49844        fbt            kernel          ufs_setacl_nfs4_internal return
49845        fbt            kernel                        ufs_setacl entry
49846        fbt            kernel                        ufs_setacl return
...
```

可以看到很多 DTrace 相關的 probe，可以用 dtrac -l 得到，從左到右邊可以看到的欄位是

* ID: 每個 probe 都有自己獨一無二的 ID
* PROVIDER: 這個 probe 的提供者，可能是
  * fbt: function bound
  * dtrace: dtrace 提供的
  * syscall: syscall
* MODULE: 這是屬於哪個 moduler，像是可能是 kernel 的函式，freebsd32 等
* FUNCTION NAME: 最小的這個 probe 的名字
* entry/return/start/done …: 指定進入 funciton 或是離開的時候

### DTrace Kernel Support

我們需要開啟一些選項，DTrace 預設在 FreeBDS GENERIC 核心有開啟。

參考 <https://docs.freebsd.org/en/books/handbook/dtrace/#dtrace-out-of-kernel> and <https://wiki.freebsd.org/DTrace/KernelSupport>。

### 基礎例子

請看 <http://cozy-kola.medium.com/freebsd-dtrace-%E7%94%A8%E6%B3%95-445c97e684cb>

<!-- TODO -->

### 基礎例子 2

請參考 [The DTrace One-Liner Tutorial](https://wiki.freebsd.org/action/logout/DTrace/Tutorial?action=logout&logout=logout)：

`dtrace:::BEGIN` 是一個特殊的函式，你可以用他來設定變數跟列印出標頭。

`dtrace -n 'syscall::open*:entry { printf("%s %s", execname, copyinstr(arg0)); }'` 這邊用到特殊的字串：

* `execname`: DTrace built-in 變數，目前正在執行這個 syscall 的 process 名字
* `arg0`: 文件名字
* `copyinstr(arg0)`: 把 user-space 的 C string 複製進 kernel space，可以讓我們列印出來

`dtrace -n 'syscall:::entry { @[execname, probefunc] = count(); }'` 用到：

* `probefunc`: syscall 用到的名字
* `@[...]`: 聚合，計數字
* `count()`: 增加 1

```sh
dtrace -n 'syscall::read:entry { self->ts = timestamp; } syscall::read:return /self->ts/ {
    @ = quantize(timestamp - self->ts); self->ts = 0; }'
```

如上，用 `self->ts` 儲存現在時間，`self-ts` 是每個 thread 的 local 變數。

## DTrace Script

並且 FreeBSD 提供很多現有的 DTrace script 來用，像是在 /usr/share/dtrace 還有 [sysutils/dtrace-toolkit](https://cgit.freebsd.org/ports/tree/sysutils/dtrace-toolkit/) 套件 (套件上的不一定全部能用)。

同樣請看 <http://cozy-kola.medium.com/freebsd-dtrace-%E7%94%A8%E6%B3%95-445c97e684cb>

<!-- TODO -->

## Kernel Module

我們也可以在 Kernel module 上面開啟 DTrace 來 debug module。你可以用 DTrace 追蹤載入模組的函式，像是自己寫的 MAC Module 裡面有一個 Utility function `casper_deny_default` 我可以用下面指令來追蹤。

```sh
kola@generic:~/proj/mac_casper/test/performance/macro/sockstat $ sudo dtrace -n 'fbt:casper_deny_default::return { printf("%s returned %d", probefunc, arg1); }'
dtrace: description 'fbt:mac_casper::return ' matched 133 probes
```

或者指定回傳為特定值的追蹤：`dtrace -n 'fbt:mac_casper::return /arg1 == 13/ { printf("%s() in %s returned EACCES (13)", probefunc, execname); }'`

## Reference

* [An introduction](https://gist.github.com/bijanebrahimi/4bd747332896e2eb59964e205122dc4b)
* [FreeBSD DTrace and truss 用法](https://cozy-kola.medium.com/freebsd-dtrace-%E7%94%A8%E6%B3%95-445c97e684cb)
* [DTrace wiki](https://en.wikipedia.org/wiki/DTrace)
* [Chapter 27. DTrace](https://docs.freebsd.org/en/books/handbook/dtrace/)
* [Linux动态追踪技术简介](https://lawrencezx.github.io/blogs/2022-3-Linux-Dynamic-Tracing.html)
* [Linux黑科技：浅析动态追踪技术](https://zhuanlan.zhihu.com/p/685805240)

