容器中的診斷與分析4——live diagnosis——LTTng LTTng 簡介&使用實戰

官網地址html

LTTng 簡介&使用實戰python

使用LTTng連接內核和用戶空間應用程序追蹤linux

 

簡介:算法

LTTng: (Linux Trace Toolkit Next Generation),它是用於跟蹤 Linux 內核、應用程序以及庫的系統軟件包shell

LTTng 主要由內核模塊和動態連接庫(用於應用程序和動態連接庫的跟蹤)組成緩存

由一個會話守護進程控制,該守護進程接受來自命令行接口的命令安全

 babeltrace 項目容許將追蹤信息翻譯成用戶可讀的日誌,並提供一個讀追蹤庫,即 libbabletrace。babel

 

  •  LTTng 不只使用了 Linux 內核中的追蹤點(tracepoint)手段,並且可使用其餘各類信息來源,
    • 好比kprobes 和 Perf(Linux 中的性能監檢測工具)。
  • 這對於調試大範圍內的bug 是很是有用的,不然這種調試工做將極具挑戰性。
    • 好比,包括並行系統和實時系統中的性能問題。
  • 另外,用戶本身定製的工具也能夠加入到其中。
    • LTTng 的設計目標是將性能影響最小化,並且在沒有跟蹤的狀況下,對系統的影響應該幾乎爲零。

 

LTTng現在已支持多個發行版(Ubuntu/Dibian、Fedora、OpenSUSE、Arch etc.)和多種架構(x86 and x86-64 、ARM 、PowerPC, Sparc, Mips etc.),此外官方還說支持Android和FreeBSD系統。網絡

 

 

實戰:session

  • 首先咱們得確認你是否已經安裝了lttng-modules 和lttng-tools。
  • 列出全部的可追蹤內核事件: 
# lttng list -k
Kernel events:
-------------
     timer_init (loglevel: TRACE_EMERG (0)) (type: tracepoint)
     timer_start (loglevel: TRACE_EMERG (0)) (type: tracepoint)
     timer_expire_entry (loglevel: TRACE_EMERG (0)) (type: tracepoint)
 ……
  • 建立一個追蹤會話(session),這個命令會建立一個目錄用以存放追蹤結果:

    # lttng create mysession
    Session mysession created.
    Traces will be written in /home/dslab/lttng-traces/mysession-20131010-145153

    • 假如你當前已經有了不少的會話,咱們能夠設置當前追蹤會話:
# lttng set-session myothersession
Session set to myothersession
  • 建立追蹤規則(探測點/系統調用 etc.)

    • 追蹤內核全部的探測點和全部的系統調用事件(-k/--kernel):
      • # lttng enable-event -a -k  
    • 追蹤探測點事件,這裏咱們追蹤 sched_switch和sched_wakeup爲例 (-k/--kernel) ;或者追蹤全部的探測點事件:
      • # lttng enable-event sched_switch,sched_wakeup -k
      • # lttng enable-event -a -k --tracepoint
    • 追蹤全部的系統調用:
      • # lttng enable-event -a -k --syscall
    • 使用 kprobes 以及 (或) 其餘追蹤器做爲lttng的源:
      • 這是一個LTTng2.0內核追蹤器的一個新特性,你可使用一個動態probe做爲源,probe的追蹤結果會顯示在lttng的追蹤結果中。
      • 能夠爲probe制定一個準確的地址0xffff7260695或者 symbol+offset。
        • lttng enable-event aname -k --probe 0xffff7260695
        • lttng enable-event aname -k --probe symbol+0x0
      • 也可使用功能追蹤(使用的Ftrace API),追蹤結果也會顯示在lttng的追蹤結果中
        • lttng enable-event aname -k --function <symbol_name>
    • 打開一個事件的上下文信息:
      • 這也是一個新特性,可讓你添加一個事件的上下文信息。
        • 好比說你能夠添加PID:# lttng add-context -k -e sched_switch -t pid
      • 也可使用多個上下文信息:
        • # lttng add-context -k -e sched_switch -t pid -t nice -t tid
      • 可使用' lttng add-context --help ' 學習全部的上下文格式的用法。
    • 打開事件的Perf計數器: 
      • 這也是一個新的很強大的特性,爲每一個追蹤的事件添加Perf計數器數據(使用Perf的API)。
        • 下面實例爲爲每一個事件添加CPU週期:# lttng add-context -k -e sched_switch -t perf:cpu-cycles
      • 注: 你須要使用 add-context 的help學習全部的perf計數器值的含義
  • 開始追蹤
    • # lttng start
    • 追蹤結果會寫到上面建立會話時建立的文件夾中。
      • 好比上面的 :/home/dslab/lttng-traces/mysession-20131010-145153
    • 注意:這個命令會打開全部的追蹤,若是你想同時追蹤用戶空間和內核空間,你在使用這個以前須要設置好全部的追蹤規則。

 

  • 中止追蹤
    • # lttng stop
    • 注:在這時候,你可一使用 lttng start 從新追蹤,也能夠打開/關閉某個事件或者隔段時間再來追蹤。固然你也能夠查看追蹤信息。

 

  • 關閉追蹤(你的追蹤工做已經結束)
    • # lttng destroy 

 

用戶空間追蹤:

追蹤數據分析:

 

  • 分析工具 -- babeltrace
    • babeltrace是lttng tools中自帶的分析工具,很強大。
    • 能夠直接使用babeltrace打開追蹤數據
      • 好比上面提到的 /home/dslab/lttng-traces/mysession-20131010-145153。
    • 先查看下這個追蹤結果下的結構:
      • # tree /home/dslab/lttng-traces/mysession-20131010-145153
         
        
        /home/dslab/lttng-traces/mysession-20131010-145153
        └── kernel
            ├── channel0_0 
            ├── channel0_1 
            ├── channel0_2 
            ├── channel0_3 
            └── metadata
      • 能夠看出來追蹤目錄下只有一個目錄,叫作kernel;若是追蹤前也打開了用戶追蹤,那麼這裏面還會多個追蹤目錄(用戶空間的)
      • kernel目錄下分幾個文件保存追蹤數據。可是咱們使用babeltrace查看追蹤結果時不能指定到具體的文件,須要指定到kernel。
    • 若是咱們將babeltrace的輸出信息輸出到一個文件中,咱們就可使用shell腳本獲取/tmp/trace中的追蹤數據並進一步分析。
      • 好比# babeltrace /home/dslab/lttng-traces/mysession-20131010-145153 > /tmp/trace 。

 

原文連接

LTT:(Linux Trace Toolkit)是linux下一種用於跟蹤系統詳細運行狀態和流程的重要工具,它能夠跟蹤記錄系統中的特定事件。

這些事件包括:
* 系統調用的進入和退出
* 陷阱/中斷(Trap / Irq)的進入和退出
* 進程調度事件
* 內核定時器
* 進程管理相關事件:建立 ,喚醒,信號處理等等
* 文件系統相關事件:Open / Read / Write / Seek / Ioctl 等等
* 內存管理相關事件:內存分配/釋放等
* 其餘事件:IPC / Socket/ 網絡 等等
此外 Ltt還提供了自定義和記錄須要跟蹤的事件類型的函數接口。

 

LTTng: (Linux Trace Toolkit Next Generation),它是用於跟蹤 Linux 內核、應用程序以及庫的系統軟件包。

LTTng 主要由內核模塊和動態連接庫(用於應用程序和動態連接庫的跟蹤)組成。

它由一個會話守護進程控制,該守護進程接受來自命令行接口的命令。

babeltrace 項目容許將追蹤信息翻譯成用戶可讀的日誌,並提供一個讀追蹤庫,即 libbabletrace。
LTTng 不只使用了 Linux 內核中的追蹤點(tracepoint)手段,並且使用了其餘各類信息來源,好比kprobes 和 Perf(Linux 中的性能監檢測工具)。

這對於調試大範圍內的bug 是很是有用的,不然這種調試工做將極具挑戰性。好比,包括並行系統和實時系統中的性能問題。

另外,用戶本身定製的工具也能夠加入到其中。LTTng 的設計目標是將性能影響最小化,並且在沒有跟蹤的狀況下,對系統的影響應該幾乎爲零。

 

LTTng2.0:使用簡單的用戶接口--lttng命令來整合用戶空間和內核空間追蹤。

還有其餘一些特性:

  • 從支持多個發行版 & 多個架構
  • 有通用的追蹤格式
  • 支持探測點、詳細的系統調用追蹤、函數追蹤器、CPU性能監控以及kprobe
  • 提供對用戶空間和內核的追蹤接口
  • 能夠在追蹤中的事件附加上下文信息(好比PMU 性能監控單元counter, pid, ppid, tid, comm name等)。全部的額外信息都被收集起來放在一個追蹤session的部件裏。

 

研究背景

     現現在,多核、集羣以及嵌入式系統等讓Linux系統變得愈來愈複雜,而開發者就面臨着愈來愈複雜的bug,這些bug可能只在產品中出現而在調試時就不見了或者不多發生並且只讓系統變得有點慢,這些特性都讓傳統的調試內核工具變得無效。因此須要有調試工具來應對這些問題。這些工具對系統的性能影響必要要很小,從而能夠把他們用在產品上。
     內核追蹤就是一款這樣的工具,它提供了一種頗有效的理解內核行爲以及調試用戶空間程序和內核故障的方法。可是在一些狀況下,內核追蹤也是不足以應對的。好比,有個程序會發出大量的請求或者它有不少不少個線程從而致使只從內核空間的角度來追蹤是很是難的。因此在這種狀況下,應用空間的程序也須要追蹤。並且要求追蹤的用戶空間事件與內核事件是相關的。
     本文提到的是LTTng的一個用戶空間追蹤器,能夠實現上述功能 --  同時追蹤用戶空間應用程序事件和內核事件。

 

What is tracing?

     追蹤是一門技術用來理解或者監控系統裏面是如何運行的。追蹤器(tracer)是用來追蹤的軟件。追蹤能夠用來調試不少的bug,這些可能包括複雜的並行系統或者實時系統中的性能問題。
     追蹤其實和記錄日誌很像:它主要就是記錄系統中的事件。可是,與日誌相比,它記錄的是系統中更爲底層以及更頻繁的事件。因此追蹤其必須被優化從而能夠處理大量的數據而不對系統產生很大的影響。追蹤其一般一秒鐘產生數以千計的事件。它們常常處理數以百萬計的事件以及數M到數十G的數據。
     追蹤可能包括操做系統內核的各類事件(好比中斷請求處理函數的進入/退出,系統調用的進入/退出,調度狀況以及網絡狀況等),他們還可能包括應用程序的事件。
     事件追蹤的列表可能被手動的像讀取日誌文件那樣讀取,可是由於工做量太大,因此追蹤分析器或者閱讀器能夠根據這些龐大的數據生成圖型或者統計數據。這些分析軟件須要特殊設計以便快讀處理這些龐大的數據。

 

相關研究

* strace :是一種提供原始的用戶空間追蹤的工具,它能夠追蹤系統調用和信號的狀況。可是它會引起較大的性能損失。可是它限制到追蹤一些系統調用和信號,能夠以較小的損失來得到追蹤信息。

* DTrace :具備靜態定義的跟蹤(Statically Defined Tracing,SDT)能夠用在用戶空間應用中。它用一種在運行時連接中的特殊支持實現的。【6】

* SystemTap :如同DTrace實現了SDT。【2】

* LTTng : 這些年提供了幾種不一樣的用戶空間追蹤技術:

1)systemcall assisted -- 這個技術聲明瞭兩個新的系統調用,第一個用來註冊一個事件類型並返回事件ID,第二種用來記錄事件,他須要事件ID和負荷
2) userspace tracing -- 它不須要內核的支持。程序在他們本身的地址空間緩存上寫事件,追蹤器爲每一個線程穿件一個共享緩存的同伴進程,同伴進程使用一個無鎖算法來使用這個緩存。

---- 這兩個方法都被遺棄了,如今有個新的替代方案被提出,它是一個簡單的使用字符串作參數的系統調用。調用它會產生一個參數就是這個字符串的事件,…… 。這個特性是來自於DebugFS(/debug/ltt/write_event),向這個文件寫入一個字符就會建立一個叫作user-space_event的事件,事件的參數是這個字符串。

* Ftrace :有相似的特性,叫作trace_marker.

 

實現 

主要介紹UST(LTTng Userspace Tracer,LTTng用戶空間追蹤器)的結構,首先咱們看看UST的重要設計目標:
   * 須要與內核空間的追蹤器徹底獨立,用戶空間追蹤和內核空間追蹤的結果應該在分析的時候再關聯
   * 須要是可重入的,並支持多線程&追蹤信號處理的事件
   * 在快速路徑中不能有系統調用
   * 追蹤結果不能被拷貝
   * 須要能追蹤共享庫中的代碼
   * 探測點須要支持無窮多的參數
   * 對於鏈接器和編譯器不須要特殊的支持
   * 追蹤格式須要是緊湊的

 

追蹤庫 

* libust - 追蹤庫
* liburcu - 用戶空間讀/拷貝/更新庫,用來在數據結構之間無鎖操控【4】
* libkcompat - Linux內核提供用戶空間API的庫(如院子看哦乃至,鏈接表機制,kref類型機制等)【5】

 

時間

     LTTng的用戶空間追蹤器和內核沒有依賴關係,可是爲了把內核追蹤和用戶空間追蹤合併分析,全部的追蹤器的時間戳必須是一致的(必須來自同樣的時鐘源)。
     一個合適的時鐘源必須是高精度的這樣才能保證在覈之間都是一致的;還要保證用戶空間和內核空間訪問時的開銷要小(由於系統調用的代價以及很高了)。
UST中使用的是內核提供的時鐘源,並且直接使用rdtsc指令讀取。這個時鐘源也是內核追蹤器使用的,讀取和多核之間同步都很快。

 

探測點

     探測點是由內核LTTng使用的兩個端口組成:marker和tracepoint,它們的使用也與內核中同樣。
     插入marker就像在事件須要記錄的地方插入一行代碼同樣簡單,下面的代碼中咱們能夠看到,mark的使用與printf很相似:
                       trace_mark(main,myevent,"firstarg %d secondarg %s",v,st);
     tracepoint的設計更佳,從下面代碼中能夠看到,它基本不包括一個格式字符串,但須要一些聲明,通常分開放在C文件和頭文件中。因此,它更合適放在永久的代碼中(須要時,只須要修改頭文件中聲明便可)。而marker更合適用在調試時添加。(用來調試中打印信息)
                       trace_main_myevent(v,st);
     marker和tracepoint在可執行或者動態對象中的一個特殊字段列舉他們自身信息,全部包含探測點的庫和可執行文件所以須要經過調用追蹤庫來註冊他們的marker/tracepoint。這是經過喚醒一個添加構造函數的宏來實現的。

 

 

緩存機制 

     緩存機制是無鎖LTTng算法的一個端口,它的設計不少源自於K42操做系統以及Linux內核中的Relay系統【8】事件在一個圓形的、每一個進程一個的緩衝區中被寫入,這個緩衝區被劃分紅多個sub-buffer。默認狀況下,當一個sub-buffer寫滿,就會有一個清空守護進程清空它。在另一種操做模式下(flight recorder),圓形的緩衝區被不斷的重寫直到這個緩衝區被清除,這對於等待一些罕見的bug出現是頗有幫助的。
     每一個事件都與一個channel(通道?)相關聯,對於每一個channel每一個進程都有個明顯的緩衝區。有幾個channel容許選擇每一個channel的sub-buffer大小。在flight recorder模式下,它經過將一些時間放在低速率的緩衝區中實現容許保持這些事件的緩衝區很長的時間。
     緩衝區被分配在System V的共享內存字段中,因此清空守護進程能夠將它們映射到它本身的地址空間。
     寫緩衝區時使用了一種已形式化驗證過其安全性的無鎖算法,因此能夠保證可重入、多線程、安全性。

 

追蹤控制

      用戶空間追蹤器確定須要一個控制方法,好比咱們須要開始/中止追蹤、使能/關閉/列出探測點以及控制追蹤參數(好比sub-buffer的大小以及數量)
      一個叫作ust的輔助應用被設計用來作這項工做,它與被追蹤的程序經過UNIX socket通訊,被追蹤哦進程中一個特殊的線程來處理這個通訊。這個線程並非當這個應用程序開始時就啓動,這使得UST看起來不是那麼有攻擊性。而是,當追蹤庫構造函數爲一個特別的信號註冊一個信號控制器,當那個信號被接收到,這個監聽的線程纔會啓動。這個線程會在一個預先定義好的目錄下建立一個socket,socket的名爲進程ID。

 

數據收集 

      有一個進程收集系統中全部被追蹤的進程的追蹤數據,這個進程叫作ustd。收集數據使用一個命名socket,socket會調用ustd 並定位到與被追蹤的程序的socket一樣的目錄下。經過這個socket,ustd才能接受指令並收集給定PID對應的緩存的追蹤數據。
      收到指令後,ustd會建立一個線程用來連接socket和被追蹤的進程。首先,假如socket還沒準備好它會發送一個SIGIO信號,而後,它會請求共享內存以求映射緩存。
      直到可以使用被追蹤應用的socket後,這個線程會發一個請求來獲取下一個sub-buffer的許可。當下一個sub-buffer滿了後,會發送一個回覆。收到回覆後,這個線程會將他的數據寫到追蹤文件中(從共享內存段中讀取的)。

 

過早和過晚地追蹤

       UST使用一種特殊的機制用來保證在程序執行時開始追蹤:用兩個環境變量運行這個程序,這些環境變量被追蹤庫構造函數解析,設定這些環境變量是爲了保證在程序進入他的main()函數時追蹤已然開始。       但對於程序結束時如何結束跟蹤難度比較大:可能程序崩潰了而後就沒辦法通知ustd來獲取最後一個sub-buffer的信息,更壞的多是在追蹤還沒映射它的緩存程序就結束了。對於前面的狀況,追蹤的最後一部分就丟失了;對於後面的狀況,整個追蹤就丟失了,由於內核會在使用者與共享內存段斷開鏈接時解除分配這段共享內存。      當程序崩潰時,內核會關閉socket鏈接,可是ustd可以檢測到socket的斷開,並在緩存上運行一個崩潰恢復程序,這個程序會辨別哪一個sub-buffer有還沒記錄的數據以及有多少數據能夠被恢復,這些數據會被恢復程序追加到追蹤文件後。對於如何辨別sub-buffer中的數據是否是有效的,使用的是一些在映射緩存與共享內存段的原子算法中用到的計數器。      當程序的生命週期對於ustd來講過短了,來不及映射內存,新的難題出現了。(目前UST還沒支持這種狀況下的追蹤)可是計劃是使用析構函數來處理這個問題,假如追蹤庫的析構函數檢測到一個追蹤被記錄可是他的緩衝區還未被映射,它會擴展程序的生命週期來給ustd足夠的時間映射。

相關文章
相關標籤/搜索