CNDI
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights New
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Help
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # 常用的除錯技巧 ## 課程目標 - 使用 pprof 進行除錯 - 使用 delve 進行除錯 - 認識 eBPF :::info 延伸閱讀: [Linux 核心設計: 透過 eBPF 觀察作業系統行為](https://hackmd.io/@sysprog/linux-ebpf) ::: ## 使用 pprof 進行除錯 pprof 是由 golang 官方維護的效能分析(profiling)套件,它能夠輸出可視覺化的分析紀錄。讓我們根據這些資訊了解 heap 以及 cpu 的使用量。 ```go= import ( "fmt" "net/http" _ "net/http/pprof" ) func main() { http.ListenAndServe("localhost:6060", nil) } ``` 在主程式的入口點引入 `_ "net/http/pprof"` 並且使用 `http.ListenAndServe("localhost:6060", nil)`,這樣一來,當程式執行時 pprof 就會被啟用。 程式執行的過程中,我們可以使用瀏覽器訪問 http://localhost:6060/debug/pprof/ ![image](https://hackmd.io/_uploads/r1wpkqmxWx.png) *使用 Gthulhu + pprof 觀察記憶體分配狀況* 如果覺得文字難以閱讀,可以使用 go tool pprof 讀取 Count Profile 列出的資訊,例如: - heap 對應 http://localhost:6060/debug/pprof/heap - goroutine 對應 http://localhost:6060/debug/pprof/goroutine ```shell $ go tool pprof http://localhost:6060/debug/pprof/heap Fetching profile over HTTP from http://localhost:6060/debug/pprof/heap Saved profile in /home/ian/pprof/pprof.main.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz File: main Build ID: c27815f62575d47a5fe5c40c1c7591152986d351 Type: inuse_space Time: Nov 14, 2025 at 1:09am (CST) Entering interactive mode (type "help" for commands, "o" for options) (pprof) (pprof) exit ``` 若一切順利,你會取得一個經過處理的檔案 `/home/ian/pprof/pprof.main.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz`,接著我們再使用 `go tool pprof` 提供的 WEB GUI 讀取它: ```shell $ go tool pprof -http=:8080 /home/ian/pprof/pprof.main.alloc_objects.alloc_space.inuse_objects.inuse_space.001.pb.gz ``` 你就能透過瀏覽器了解 Gthulhu 在運作時的記憶體分配狀況: ![image](https://hackmd.io/_uploads/Hkugf97xZg.png) 換成 goroutine 也是類似的概念: ![image](https://hackmd.io/_uploads/S1-lG97xWl.png) ## 使用 delve 進行除錯 [delve](https://github.com/go-delve/delve) 是一個為 golang 開發的 debbuger,概念與 GDB 並無差別。 在某些情境下,Debugger 可以幫助我們找出程式的非預期行為,例如: - 網路程式有收到封包,但不確定處理完封包後程式的 context 是否如我們預期 - 確定程式流,尤其是使用並行程式開發的程式 Debbuger 雖然好用,但也不是萬用的,像是嘗試在 http request 的 handler 設置中斷點,但 http request 本身是有時限性的,如果在中斷點停留過久反而會增生其他問題,導致原本的問題無法被原況呈現。在不同的情境下,選用不同的除錯工具才能有效解決問題。 ![image](https://hackmd.io/_uploads/SkPpFqmeZg.png) 如果你使用的是 VSCode,請安裝 Go extension,該套件包含了 delve 執行所需要的環境。有了 Go extension,我們就能在 IDE 上直接使用 debugger 的功能: ![image](https://hackmd.io/_uploads/rkhM5cXl-g.png) 參考上圖,我們能夠直接在程式碼行數左方按下右鍵直接插入一個中斷點。 要在 VSCode 上直接使用 delve 除錯,請在工作目錄下建立以下檔案: ```bash= code .vscode/launch.json ``` 並且將以下內容貼上 `.vscode/launch.json` ```json= { // Use IntelliSense to learn about possible attributes. // Hover to view descriptions of existing attributes. // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "name": "Launch Package", "type": "go", "request": "launch", "mode": "auto", "program": "${fileDirname}" }, { "name": "Attach to Process", "type": "go", "request": "attach", "mode": "local", "processId": "${command:pickProcess}" }, { "name": "Attach via Headless Delve", "type": "go", "request": "attach", "mode": "remote", "remotePath": "", "port": 2345, "host": "127.0.0.1" } ] } ``` - 碰到 `try writing "0" to /proc/sys/kernel/yama/ptrace_scope` 問題時,請執行 `echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope`。 - 第三種方式需要額外運作 delve,如:`sudo dlv attach <PID> --headless --listen=:2345 --api-version=2`,`<PID>` 請填入你要進行除錯的程式。 成功後,你會看到以下畫面: ![image](https://github.com/golang/vscode-go/wiki/images/attach.gif) *圖片來源:https://github.com/golang/vscode-go/wiki/debugging* ## eBPF (extended BPF) eBPF 的 "BPF" 來自一篇 1992 年發表的論文「The BSD Packet Filter: A New Architecture for User-level Packet Capture」。這篇論文引入 instruction set 幫助開發者有效的監測網路流量。 如今的 eBPF 與 BPF(又稱 Classic BPF)並沒有太大的關聯,eBPF 最早是由 Plumgrid 開發,稱之為 "iovisor.ko"。後面為了貢獻至 Linux Kernel 的上游,在經過一番努力後變成現在的 eBPF。 ![image](https://hackmd.io/_uploads/HkaWZsmxZe.png) Kernel 允許使用者將經過編譯產生的 eBPF program 以探針的形式注入到系統之中。可以注入的觀測點有上百個,主要涵蓋: - 網路子系統 - 檔案系統 - 系統呼叫 - 內部函式的動態追蹤 - 排程器(sched_ext) - ...,不勝枚舉 eBPF 之所以這麼熱門,除了千變萬化的應用場景外,最大的原因就是安全性,它能夠保證 eBPF program 注入到系統後不會造成 kernel panic,這對於 kernel developer 來說是一大福音。 ![image](https://hackmd.io/_uploads/SyYEXsmxbx.png) 追求絕對的安全性勢必需要犧牲一定程度的彈性,所有的 eBPF program 在使用 C 語言撰寫時就受到強烈的規範: - 僅能使用特定的 eBPF library - 編譯後的 instruction size 有限制,記憶體用量也有限制 - 僅能在[有限的情況下](https://docs.ebpf.io/linux/concepts/loops/)使用 loop 諸多限制下,在開發 eBPF program 時經常會因為不符合 eBPF verifier 的要求而被擋下: ![image](https://hackmd.io/_uploads/H1dm7jQeZx.png) ### 與 user space app 互動 eBPF 的使用場景多半出現在動態追蹤上,當我們在系統中注入大量的 eBPF program 蒐集目標事件,背後也需要一個應用程式來消化這些資料。 eBPF 提供 Map(以 key-value 的方式進行儲存),eBPF program 與 user space app 都能夠存取 eBPF Map: ![image](https://hackmd.io/_uploads/BkVEEjmeZx.png) 事實上,各位在 Project 3 使用的 Gthulhu 就高度的利用 eBPF Map: ![image](https://hackmd.io/_uploads/SypUViXgWx.png) 除了 Gthulhu,還有許多讓人驚艷的 eBPF 應用: - 使用 eBPF 開發 TCP congestion controler:https://github.com/orace-github/ebpf-coupled-congestion-controler - 使用 eBPF 開發 5G UPF:https://github.com/edgecomllc/eupf - 使用 eBPF 在 PF_PACKET Socket 上實作 Receive Packet Steering:https://github.com/acassen/bpf-pfpacket-rps - 使用 eBPF 追蹤封包流量:https://github.com/cilium/pwru - 使用 eBPF 實作可觀測性平台:https://github.com/coroot/coroot

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully