自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

在 Fedora 中用 bpftrace 追蹤代碼

系統(tǒng) Linux
bpftrace 是一個(gè) 基于 eBPF 的新型追蹤工具,在 Fedora 28 第一次引入。這篇文章的內(nèi)容涉及了 bpftrace 的一些基礎(chǔ),以及它是如何工作的,請(qǐng)繼續(xù)閱讀獲取更多的信息和一些有用的實(shí)例。

[[414460]]

bpftrace 是一個(gè) 基于 eBPF 的新型追蹤工具,在 Fedora 28 第一次引入。Brendan Gregg、Alastair Robertson 和 Matheus Marchini 在網(wǎng)上的一個(gè)松散的黑客團(tuán)隊(duì)的幫助下開發(fā)了 bpftrace。它是一個(gè)允許你分析系統(tǒng)在幕后正在執(zhí)行的操作的追蹤工具,可以告訴你代碼中正在被調(diào)用的函數(shù)、傳遞給函數(shù)的參數(shù)、函數(shù)的調(diào)用次數(shù)等。

這篇文章的內(nèi)容涉及了 bpftrace 的一些基礎(chǔ),以及它是如何工作的,請(qǐng)繼續(xù)閱讀獲取更多的信息和一些有用的實(shí)例。

eBPF(擴(kuò)展的伯克利數(shù)據(jù)包過濾器extended Berkeley Packet Filter

eBPF 是一個(gè)微型虛擬機(jī),更確切的說是一個(gè)位于 Linux 內(nèi)核中的虛擬 CPU。eBPF 可以在內(nèi)核空間以一種安全可控的方式加載和運(yùn)行小型程序,使得 eBPF 的使用更加安全,即使在生產(chǎn)環(huán)境系統(tǒng)中。eBPF 虛擬機(jī)有自己的指令集架構(gòu)(ISA),類似于現(xiàn)代處理器架構(gòu)的一個(gè)子集。通過這個(gè) ISA,可以很容易將 eBPF 程序轉(zhuǎn)化為真實(shí)硬件上的代碼。內(nèi)核即時(shí)將程序轉(zhuǎn)化為主流處理器架構(gòu)上的本地代碼,從而提升性能。

eBPF 虛擬機(jī)允許通過編程擴(kuò)展內(nèi)核,目前已經(jīng)有一些內(nèi)核子系統(tǒng)使用這一新型強(qiáng)大的 Linux 內(nèi)核功能,比如網(wǎng)絡(luò)、安全計(jì)算、追蹤等。這些子系統(tǒng)的主要思想是添加 eBPF 程序到特定的代碼點(diǎn),從而擴(kuò)展原生的內(nèi)核行為。

雖然 eBPF 機(jī)器語言功能強(qiáng)大,由于是一種底層語言,直接用于編寫代碼很費(fèi)力,bpftrace 就是為了解決這個(gè)問題而生的。eBPF 提供了一種編寫 eBPF 追蹤腳本的高級(jí)語言,然后在 clang / LLVM 庫的幫助下將這些腳本轉(zhuǎn)化為 eBPF,最終添加到特定的代碼點(diǎn)。

安裝和快速入門

在終端 使用 sudo 執(zhí)行下面的命令安裝 bpftrace:

  1. $ sudo dnf install bpftrace

使用“hello world”進(jìn)行實(shí)驗(yàn):

  1. $ sudo bpftrace -e 'BEGIN { printf("hello world\n"); }'

注意,出于特權(quán)級(jí)的需要,你必須使用 root 運(yùn)行 bpftrace,使用 -e 選項(xiàng)指明一個(gè)程序,構(gòu)建一個(gè)所謂的“單行程序”。這個(gè)例子只會(huì)打印 “hello world”,接著等待你按下 Ctrl+C。

BEGIN 是一個(gè)特殊的探針名,只在執(zhí)行一開始生效一次;每次探針命中時(shí),大括號(hào) {} 內(nèi)的操作(這個(gè)例子中只是一個(gè) printf)都會(huì)執(zhí)行。

現(xiàn)在讓我們轉(zhuǎn)向一個(gè)更有用的例子:

  1. $ sudo bpftrace -e 't:syscalls:sys_enter_execve { printf("%s called %s\n", comm, str(args->filename)); }'

這個(gè)例子打印了父進(jìn)程的名字(comm)和系統(tǒng)中正在創(chuàng)建的每個(gè)新進(jìn)程的名稱。t:syscalls:sys_enter_execve 是一個(gè)內(nèi)核追蹤點(diǎn),是 tracepoint:syscalls:sys_enter_execve 的簡(jiǎn)寫,兩種形式都可以使用。下一部分會(huì)向你展示如何列出所有可用的追蹤點(diǎn)。

comm 是一個(gè) bpftrace 內(nèi)建指令,代表進(jìn)程名;filename 是 t:syscalls:sys_enter_execve 追蹤點(diǎn)的一個(gè)字段,這些字段可以通過 args 內(nèi)建指令訪問。

追蹤點(diǎn)的所有可用字段可以通過這個(gè)命令列出:

  1. bpftrace -lv "t:syscalls:sys_enter_execve"

示例用法

列出探針

bpftrace 的一個(gè)核心概念是探針點(diǎn)probe point,即 eBPF 程序可以連接到的(內(nèi)核或用戶空間的)代碼中的測(cè)量點(diǎn),可以分成以下幾大類:

  • kprobe——內(nèi)核函數(shù)的開始處
  • kretprobe——內(nèi)核函數(shù)的返回處
  • uprobe——用戶級(jí)函數(shù)的開始處
  • uretprobe——用戶級(jí)函數(shù)的返回處
  • tracepoint——內(nèi)核靜態(tài)追蹤點(diǎn)
  • usdt——用戶級(jí)靜態(tài)追蹤點(diǎn)
  • profile——基于時(shí)間的采樣
  • interval——基于時(shí)間的輸出
  • software——內(nèi)核軟件事件
  • hardware——處理器級(jí)事件

所有可用的 kprobe / kretprobe、tracepointssoftware 和 hardware 探針可以通過這個(gè)命令列出:

  1. $ sudo bpftrace -l

uprobe / uretprobe 和 usdt 是用戶空間探針,專用于某個(gè)可執(zhí)行文件。要使用這些探針,通過下文中的特殊語法。

profile 和 interval 探針以固定的時(shí)間間隔觸發(fā);固定的時(shí)間間隔不在本文的范疇內(nèi)。

統(tǒng)計(jì)系統(tǒng)調(diào)用數(shù)

映射 是保存計(jì)數(shù)、統(tǒng)計(jì)數(shù)據(jù)和柱狀圖的特殊 BPF 數(shù)據(jù)類型,你可以使用映射統(tǒng)計(jì)每個(gè)系統(tǒng)調(diào)用正在被調(diào)用的次數(shù):

  1. $ sudo bpftrace -e 't:syscalls:sys_enter_* { @[probe] = count(); }'

一些探針類型允許使用通配符匹配多個(gè)探針,你也可以使用一個(gè)逗號(hào)隔開的列表為一個(gè)操作塊指明多個(gè)連接點(diǎn)。上面的例子中,操作塊連接到了所有名稱以 t:syscalls:sysenter_ 開頭的追蹤點(diǎn),即所有可用的系統(tǒng)調(diào)用。

bpftrace 的內(nèi)建函數(shù) count() 統(tǒng)計(jì)系統(tǒng)調(diào)用被調(diào)用的次數(shù);@[] 代表一個(gè)映射(一個(gè)關(guān)聯(lián)數(shù)組)。該映射的鍵 probe 是另一個(gè)內(nèi)建指令,代表完整的探針名。

這個(gè)例子中,相同的操作塊連接到了每個(gè)系統(tǒng)調(diào)用,之后每次有系統(tǒng)調(diào)用被調(diào)用時(shí),映射就會(huì)被更新,映射中和系統(tǒng)調(diào)用對(duì)應(yīng)的項(xiàng)就會(huì)增加。程序終止時(shí),自動(dòng)打印出所有聲明的映射。

下面的例子統(tǒng)計(jì)所有的系統(tǒng)調(diào)用,然后通過 bpftrace 過濾語法使用 PID 過濾出某個(gè)特定進(jìn)程調(diào)用的系統(tǒng)調(diào)用:

  1. $ sudo bpftrace -e 't:syscalls:sys_enter_* / pid == 1234 / { @[probe] = count(); }'

進(jìn)程寫的字節(jié)數(shù)

讓我們使用上面的概念分析每個(gè)進(jìn)程正在寫的字節(jié)數(shù):

  1. $ sudo bpftrace -e 't:syscalls:sys_exit_write /args->ret > 0/ { @[comm] = sum(args->ret); }'

bpftrace 連接操作塊到寫系統(tǒng)調(diào)用的返回探針(t:syscalls:sys_exit_write),然后使用過濾器丟掉代表錯(cuò)誤代碼的負(fù)值(/arg->ret > 0/)。

映射的鍵 comm 代表調(diào)用系統(tǒng)調(diào)用的進(jìn)程名;內(nèi)建函數(shù) sum() 累計(jì)每個(gè)映射項(xiàng)或進(jìn)程寫的字節(jié)數(shù);args 是一個(gè) bpftrace 內(nèi)建指令,用于訪問追蹤點(diǎn)的參數(shù)和返回值。如果執(zhí)行成功,write 系統(tǒng)調(diào)用返回寫的字節(jié)數(shù),arg->ret 用于訪問這個(gè)字節(jié)數(shù)。

進(jìn)程的讀取大小分布(柱狀圖):

bpftrace 支持創(chuàng)建柱狀圖。讓我們分析一個(gè)創(chuàng)建進(jìn)程的 read 大小分布的柱狀圖的例子:

  1. $ sudo bpftrace -e 't:syscalls:sys_exit_read { @[comm] = hist(args->ret); }'

柱狀圖是 BPF 映射,因此必須保存為一個(gè)映射(@),這個(gè)例子中映射鍵是 comm。

這個(gè)例子使 bpftrace 給每個(gè)調(diào)用 read 系統(tǒng)調(diào)用的進(jìn)程生成一個(gè)柱狀圖。要生成一個(gè)全局柱狀圖,直接保存 hist() 函數(shù)到 @(不使用任何鍵)。

程序終止時(shí),bpftrace 自動(dòng)打印出聲明的柱狀圖。創(chuàng)建柱狀圖的基準(zhǔn)值是通過 args->ret 獲取到的讀取的字節(jié)數(shù)。

追蹤用戶空間程序

你也可以通過 uprobes / uretprobes 和 USDT(用戶級(jí)靜態(tài)定義的追蹤)追蹤用戶空間程序。下一個(gè)例子使用探測(cè)用戶級(jí)函數(shù)結(jié)尾處的 uretprobe ,獲取系統(tǒng)中運(yùn)行的每個(gè) bash 發(fā)出的命令行:

  1. $ sudo bpftrace -e 'uretprobe:/bin/bash:readline { printf("readline: \"%s\"\n", str(retval)); }'

要列出可執(zhí)行文件 bash 的所有可用 uprobes / uretprobes, 執(zhí)行這個(gè)命令:

  1. $ sudo bpftrace -l "uprobe:/bin/bash"

uprobe 指向用戶級(jí)函數(shù)執(zhí)行的開始,uretprobe 指向執(zhí)行的結(jié)束(返回處);readline() 是 /bin/bash 的一個(gè)函數(shù),返回鍵入的命令行;retval 是被探測(cè)的指令的返回值,只能在 uretprobe 訪問。

使用 uprobes 時(shí),你可以用 arg0..argN 訪問參數(shù)。需要調(diào)用 str() 將 char * 指針轉(zhuǎn)化成一個(gè)字符串。

自帶腳本

bpftrace 軟件包附帶了許多有用的腳本,可以在 /usr/share/bpftrace/tools/ 目錄找到。

這些腳本中,你可以找到:

  • killsnoop.bt——追蹤 kill() 系統(tǒng)調(diào)用發(fā)出的信號(hào)
  • tcpconnect.bt——追蹤所有的 TCP 網(wǎng)絡(luò)連接
  • pidpersec.bt——統(tǒng)計(jì)每秒鐘(通過 fork)創(chuàng)建的新進(jìn)程
  • opensnoop.bt——追蹤 open() 系統(tǒng)調(diào)用
  • bfsstat.bt——追蹤一些 VFS 調(diào)用,按秒統(tǒng)計(jì)

你可以直接使用這些腳本,比如:

  1. $ sudo /usr/share/bpftrace/tools/killsnoop.bt

你也可以在創(chuàng)建新的工具時(shí)參考這些腳本。

鏈接

 

責(zé)任編輯:龐桂玉 來源: Linux中國
相關(guān)推薦

2018-11-14 10:20:15

SonarQube開源追蹤代碼

2022-11-27 11:00:15

2011-07-19 17:15:29

iPhone App

2020-07-20 18:30:44

Fedora 32DockerLinux

2021-05-19 09:29:52

VueAxios異步請(qǐng)求

2022-12-03 16:02:51

2020-08-16 09:00:15

樹莓派FedoraLinux

2021-08-19 18:28:22

FedoraLinuxOpenCV

2019-10-29 16:30:10

FedoraSSH端口Linux

2025-04-03 03:55:00

2019-06-27 14:00:13

edoraMycroft開源

2022-02-09 15:29:35

Java組件編程語言

2009-12-17 09:56:01

FedoraPPStream網(wǎng)絡(luò)電視

2021-10-03 14:47:26

Fedora CoreGitHub Acti運(yùn)行器

2019-11-11 15:10:37

FedoraLinuxbash

2010-03-01 15:55:00

Fedora Eva

2020-11-26 10:25:09

FedoraPodmanLinux

2019-06-24 13:34:29

FedoraAnsible 2.8系統(tǒng)運(yùn)維

2019-07-05 18:06:18

ffsendFirefox SenLinux

2019-12-02 15:23:34

FedoraLinuxGIMP
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)