eBPF學習筆記(二)——Hello World
(英文書看嘛了,我好像在翻譯?)
Hello World
??Code
#!/usr/bin/python
from bcc import BPF
program = r"""
int hello(void *ctx) {
bpf_trace_printk("Hello World!");
return 0;
}
"""
b = BPF(text=program)
syscall = b.get_syscall_fnname("execve")
b.attach_kprobe(event=syscall, fn_name="hello")
b.trace_print()
??解讀

????hello()是將要在內核中運行的程序, 但這個python程序是運行在用戶空間的
????而hello()中只是使用了helper function: bpf_trace_printk("Hello World!")去輸出一個消息
幫助程序函數是將“extend”BPF 與其“classic”前身區分開來的另一個特性。它們是 eBPF 程序可以調用的一組函數,用于與系統交互
????但是這個C代碼需要先編譯成二進制文件才能運行
b = BPF(text=program)
????此時將返回一個BPF對象(這里都是使用python進行學習,僅僅是方便演示.但最終生產環境還是應該脫離python,手動編譯)
syscall = b.get_syscall_fnname("execve")
????此處我們選擇將eBPF程序附加到system call execve()上.雖然 “execve()” 是 Linux 中的標準接口,但在內核中實現它的函數名稱取決于芯片架構. 好在BCC 為我們提供了一種方便的方法來查找我們正在運行的機器的函數名稱,在此處用syscall儲存返回的函數名稱
????使用kprobe可以將可以將hello附加到該事件中:
b.attach_kprobe(event=syscall, fn_name="hello")
????此時,eBPF 程序被加載到內核中并附加到一個事件中,因此每當在機器上啟動新的可執行文件時,都會觸發該程序。在 Python 代碼中剩下要做的就是讀取內核輸出的跟蹤并將其寫入屏幕上:
b.trace_print()//將會無限循環

????這是書中所給示意圖. 很顯然可以看到每當有execve調用時,都回觸發hello()的執行調用,并且將一行trace寫入 pseudofile(偽文件) 中. python程序再從pseudofile中讀取trace消息并顯示.
偽文件位置:/sys/kernel/debug/tracing/trace_pipe
????此實例中只支持字符串的輸出,對于傳遞 structure作用甚微.尤其是當多個eBPF程序同時運行時,對同一跟蹤管道進行寫入------會導致一些紊亂.
????因此使用 eBPF map是必要的
[eBPF Map]

浙公網安備 33010602011771號