sysdig工作原理
Sysdig架構
具體實現(xiàn)
-
內核空間
首先,sysdig-probe 的這個驅動利用了內核組件tracepoint 捕獲在內核層面的事件。通過Tracepoint,可以放置一個能夠被內核中特殊函數(shù)調用的處理程序"handler"。現(xiàn)在,sysdig 在進入、退出、進程調度這些事件的系統(tǒng)調用上注冊了tracepoints,也即Sysdig-probe 的工作內容。Sysdig-probe對這些事件的處理程序"handler"極其簡單,它僅僅復制了事件的詳細信息到一個共享緩存區(qū)中,并對其編碼以供后面使用。讓"handler"如此簡單的一個重要原因就是性能考慮,因為原始的內核執(zhí)行程序會被“凍結”直到"handler"返回。
(tracepoint 提供了一個鉤子去調用一個函數(shù)(稱為probe,也即探針)。當一個tracepoint 被probe 連接上時便啟動了,每次tracepoint 被執(zhí)行的時候,probe 這個函數(shù)便會在調用方的執(zhí)行上下文中被調用。probe 結束執(zhí)行,返回給調用者,從tracepoint 位置繼續(xù)。)
-
用戶空間
"event buffer"使用了內存映射的方式映射到用戶空間,因此它能夠在沒有進行任何復制操作的情況下被訪問,最小化了CPU使用率和減少緩存丟失的情況。"libscap"和"libsinsp"這兩個庫提供了讀、編碼以及解析事件的功能。具體來說,"libscap"提供了跟蹤文件管理功能,而"libsinsp"包含了復雜的狀態(tài)跟蹤功能(例如,可以使用文件名而不是FD),以及過濾、事件解碼、運行"chisels"工具的Lua JIT編譯器等。
最后,sysdig 對這些庫進行了簡單的包裝。
當"event buffer"填滿(即sysdig,libsinsp,libscap 來不及處理來自內核的事件流)的時候,sysdig-probe 便會開始丟棄即將到來的事件。這種情況下可能會丟失部分跟蹤信息,但機器或者其他進程的性能不會受其影響。這意味著,sysdig很適合用在生產(chǎn)環(huán)境上。
Linux系統(tǒng)調用相關
sysdig基于系統(tǒng)調用工作。系統(tǒng)調用,指運行在用戶空間的程序向操作系統(tǒng)內核請求需要更高權限運行的服務。系統(tǒng)調用提供用戶程序與操作系統(tǒng)之間的接口。大多數(shù)系統(tǒng)交互式操作需求在內核態(tài)運行。如設備IO操作或者進程間通信
簡單地說,系統(tǒng)調用是程序與操作系統(tǒng)交互的主要方式。系統(tǒng)調用接口包含了若干個操作系統(tǒng)賦予給運行在其上的應用程序使用的函數(shù)。這些函數(shù)允許打開文件、創(chuàng)建網(wǎng)絡連接、從文件中讀寫等操作,可以說機器上大部分的事件都要經(jīng)過系統(tǒng)調用。
想要掌握sysdig的使用,我們需要掌握以下系統(tǒng)調用。
clone
- 主要工作:
創(chuàng)建新進程 - 作用:
Clone 基本上是創(chuàng)建進程和線程的唯一Linux內核入口點。這意味著你能通過查看它觀察到所有進程和線程的活動執(zhí)行。子線程中的返回值為0,父線程中的子pid為0。Clone克隆是最復雜的系統(tǒng)調用之一,有很多可以告訴你很多關于新進程正在創(chuàng)建的標志 - 注意:
Clone 是唯一返回兩次的系統(tǒng)調用,一次是在父進程,一次在子進程。
execve
- 主要工作:
執(zhí)行新的程序 - 作用:
Execve 是運行程序的唯一Linux內核入口。用戶空間API有幾種變形,比如execl和fexecve,但它們最后都會激活系統(tǒng)調用execve。你基本上總能在clone操作后看見execve操作,監(jiān)控execve操作能告訴你什么程序在你的系統(tǒng)里執(zhí)行。單一程序、腳本、定時任務都會通過execve執(zhí)行。
chdir
- 主要工作:
改變當前進程的工作目錄 - 作用:
通過chdir,能看見誰訪問了哪個目錄
open/creat
- 主要工作:
打開乃至新建一個文件或設備 - 作用:
通過追蹤這個系統(tǒng)調用,你能夠看到文件什么時候被創(chuàng)建或修改 - 注意:使用filters能夠讓在sysdig中追蹤這個系統(tǒng)調用更高效(更有趣)
sysdig evt.type=open and proc.name=evilproc and file.name contains /etc
connect
- 主要工作:
在套接字上啟動連接 - 作用:
這是建立新的網(wǎng)絡連接的唯一內核入口。每一次機器上的進程想要連接某個地方,你就能看到這個系統(tǒng)調用。 - 注意:
sysdig evt.type=connect and fd.port=80
accept
- 主要工作:
接受套接字上的連接 - 作用:
此系統(tǒng)調用鏡像連接,即每次在機器上建立服務器連接時都將看到一個鏡像連接
read/write
- 主要工作:
read 和write 系統(tǒng)調用在Linux系統(tǒng)調用接口中有很多變形,如:readv、writev、preadv、pwritev、send、recv、sendto、recvfrom、sendmsg、recvmsg、recvmmsg。它們大致上做著相同的工作,即向一個文件描述符讀寫數(shù)據(jù),這是I/O操作的核心。 - 作用:
由于在Linux上幾乎所有東西都是一個文件描述符,觀察這些調用非常方便。通過它們可以看到文件的訪問、網(wǎng)絡數(shù)據(jù)的交換、pipes的活動以及unix套接字。 - 注意:sysdig提供了一個chisel工具echo_fds讓我們能夠很方便地查看I/O活動
sysdig -c echo_fds fd.name=/etc/passwd
unlink/rename
- 主要工作:
刪除或者重命名文件 - 作用:
open/creat 系統(tǒng)調用能告訴你新建了文件,read/write 調用的變形能告訴你文件什么時候被修改,而unlink和rename 則告訴你什么時候文件被刪除和重命名
brk/mmap/munmap
- 主要工作:
分配/釋放內存 - 作用:
這些系統(tǒng)調用能讓你觀察到進程什么時候分配或者釋放內存。brk 通常由malloc()使用,而mmap/mmunmap 具有更多用途,包括共享內存或將文件映射到內存 - 注意:
內存管理極其復雜,范圍遠超出這里的內容。 由于程序中的malloc()或new()方法,你幾乎永遠不會看到brk或mmap調用,因為一般情況下你的程序在獲取其內存之前可能會經(jīng)過至少一個或兩個實體。例如,glibc有一個內存分配器,該內存分配器從內核中請求大塊連續(xù)地址的內存,然后在用戶級別進行管理。你最喜歡的基于VM語言的垃圾回收器就是執(zhí)行類似的操作。
select/poll
- 主要工作:
等待操作執(zhí)行 - 作用:
當進程沒有主動去執(zhí)行某個操作時,它們可能被這兩者之一阻塞住了。觀察它們的參數(shù)能告訴我們進程在等待什么以及等了多久。
kill
- 主要工作:
發(fā)送信號 - 作用:
kill 用于進程間發(fā)送信號
參考資料:
https://sysdig.com/blog/sysdig-vs-dtrace-vs-strace-a-technical-discussion/
https://www.kernel.org/doc/Documentation/trace/tracepoints.txt
https://sysdig.com/blog/fascinating-world-linux-system-calls/