Xentrace使用教程

介紹:

NAME 
xentrace - capture Xen trace buffer data

SYNOPSIS 
xentrace [ OPTIONS ] [ FILE ]

DESCRIPTION 
xentrace is used to capture trace buffer data from Xen. The data is output in the following binary format (host endian):     CPU(uint) TSC(u64) EVENT(u32) D1 D2 D3 D4 D5 (all u32)

Where CPU is the processor number, TSC is the record's timestamp (the value of the CPU cycle counter), EVENT is the event ID and D1...D5 are the trace data.

Data is dumped onto the standard output (which must not be a TTY) or a FILE specified on the command line.

The output should be parsed using the tool xentrace_format, which can produce human-readable output in ASCII format.

簡單來說,xentrace是用來獲取系統運行過程中一些動態信息的工具,類似Windows下的日誌。

一般使用:
系統啓動xen之後,就可以使用xentrace和xentrace_format命令了。
獲取輸出命令:xentrace -D -T 10 rec.raw
其中-D參數表明清空之前緩存的數據
-T後面跟的時間,表示需要獲取多長時間的數據(從該命令執行起開始,單位是s)

將輸出格式化爲可讀信息命令:cat rec.raw | xentrace_format formats >rec.txt
其中formats文件是xen目錄中帶的,一般在tools/xentrace下

原理探究:

查看xen源代碼可以知道,通過xentrace獲取的數據是通過TRACE_2D、TRACE_3D(2D、3D中2和3是指參數的個數)等這些記錄的數據,例如:
/xen/common/schedule.c
243 void vcpu_wake(struct vcpu *v)
244 {
.................
270     TRACE_2D(TRC_SCHED_WAKE, v->domain->domain_id, v->vcpu_id);
271 }

看一下TRACE_2D的實現代碼:
/xen/include/xen/trace.h
64 #define TRACE_2D(_e,d1,d2)                                      \
65     do {                                                        \
66         if ( unlikely(tb_init_done) )                           \
67         {                                                       \
68             u32 _d[2];                                          \
69             _d[0] = d1;                                         \
70             _d[1] = d2;                                         \
71             __trace_var(_e, 1, sizeof(*_d)*2, (unsigned char *)_d); \
72         }                                                       \
73     } while ( 0 )

可以看出,真正寫到緩衝區是通過__trace_var函數來實現的,下面來簡略看一下__trace_var

/xen/common/trace.c
416 /**
417  * trace - Enters a trace tuple into the trace buffer for the current CPU.
418  * @event: the event type being logged
419  * @d1...d5: the data items for the event being logged
420  *
421  * Logs a trace record into the appropriate buffer.  Returns nonzero on
422  * failure, otherwise 0.  Failure occurs only if the trace buffers are not y    et
423  * initialised.
424  */
這個函數將當前的trace信息輸出到log中去,方便我們後面的讀取
425 void __trace_var(u32 event, int cycles, int extra, unsigned char *extra_data    )
426 {
.................  //具體的實現我們就不細究了,有興趣的可以去分析一下
550 }


回到之前的代碼
270     TRACE_2D(TRC_SCHED_WAKE, v->domain->domain_id, v->vcpu_id);
這個函數中第一個參數是事件類型,後面是相應的數據,事件類型定義在trace.h文件中,調度這塊研究中使用較多的有以下一些:
/xen/include/public/trace.h
56 #define TRC_SCHED_VERBOSE   0x00028000   /* More inclusive scheduling */
.............
63 #define TRC_SCHED_RUNSTATE_CHANGE   (TRC_SCHED_MIN + 1)
64 #define TRC_SCHED_CONTINUE_RUNNING  (TRC_SCHED_MIN + 2)
65 #define TRC_SCHED_DOM_ADD        (TRC_SCHED_VERBOSE +  1)
66 #define TRC_SCHED_DOM_REM        (TRC_SCHED_VERBOSE +  2)
67 #define TRC_SCHED_SLEEP          (TRC_SCHED_VERBOSE +  3)
68 #define TRC_SCHED_WAKE           (TRC_SCHED_VERBOSE +  4)
69 #define TRC_SCHED_YIELD          (TRC_SCHED_VERBOSE +  5)
70 #define TRC_SCHED_BLOCK          (TRC_SCHED_VERBOSE +  6)
71 #define TRC_SCHED_SHUTDOWN       (TRC_SCHED_VERBOSE +  7)
72 #define TRC_SCHED_CTL            (TRC_SCHED_VERBOSE +  8)
73 #define TRC_SCHED_ADJDOM         (TRC_SCHED_VERBOSE +  9)
74 #define TRC_SCHED_SWITCH         (TRC_SCHED_VERBOSE + 10)
75 #define TRC_SCHED_S_TIMER_FN     (TRC_SCHED_VERBOSE + 11)
76 #define TRC_SCHED_T_TIMER_FN     (TRC_SCHED_VERBOSE + 12)
77 #define TRC_SCHED_DOM_TIMER_FN   (TRC_SCHED_VERBOSE + 13)
78 #define TRC_SCHED_SWITCH_INFPREV (TRC_SCHED_VERBOSE + 14)
79 #define TRC_SCHED_SWITCH_INFNEXT (TRC_SCHED_VERBOSE + 15)
..............
97   /* Indicates that addresses in trace record are 64 bits */        //標識64位系統
98 #define TRC_64_FLAG               (0x100)


TRACE_2D的數據最終會以二進制形式存儲(爲了節省存儲空間),通過xentrace_format可以將二進制數據轉換爲可讀的ASCII編碼的數據
xentrace_format命令最終是根據參數中formats對應文件中的數據格式來對二進制數據解釋的,下面來分析一下formats文件:
/tools/xentrace/formats
20 0x00028001  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_add_domain  [ domid = 0x%(1)08x, edomid     = 0x%(2)08x ]
21 0x00028002  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  sched_rem_domain  [ domid = 0x%(1)08x, edomid     = 0x%(2)08x ]
22 0x00028003  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_sleep      [ domid = 0x%(1)08x, edomid     = 0x%(2)08x ]
 23 0x00028004  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  domain_wake       [ domid = 0x%(1)08x, edomid     = 0x%(2)08x ]

0x00028004是事件類型標識,可以看到0x00028004就是TRC_SCHED_WAKEdomid = 0x%(1)08x, edomid     = 0x%(2)08x中(1)表示第一個參數(即dom_id),(2)表示第二個參數(即vcpu_id)

至此我們已經大概瞭解了xentrace的原理,下面來看一下xentrace的進階使用——如何添加自己所需要的輸出

進階使用(需要修改xen源代碼,並重新編譯,慎用!):
瞭解了xentrace的原理之後,那麼我們就可以來試着添加一些我們自己想要的事件類型了,首先在trace.h頭文件中定義一個TEST類型事件:
/xen/include/public/trace.h
80 #define TRC_SCHED_TEST           (TRC_SCHED_VERBOSE +  16)

然後我們想記錄一下credit調度中tickle的情況,於是在credit調度算法中添加如下一個trace輸出:
/xen/common/sched_credit.c
800 static void
801 csched_acct(void* dummy)
802 {
...........
823 // added by spri1987
824     TRACE_2D(TRC_SCHED_TEST, current->domain->domain_id, current->vcpu_id);
825 // end
............
1000 }

OK,xen源代碼修改完畢,爲了能夠生效,我們需要重新編譯我們的xen,可以使用make xen命令來編譯,編譯之後重啓系統即可生效。

下面我們來測試下我們添加的TRACE是否有記錄,獲取一個10s的TRACE信息:
xentrace -D -T 10 rec.raw

獲取之後,我們需要通過formats來格式化該二進制數據。由於我們添加了新的事件類型,因此我們需要先修改我們的formats文件:
tools/xentrace/formats
26 0x00028010  CPU%(cpu)d  %(tsc)d (+%(reltsc)8d)  do_tickle          [ domid = 0x%(1)08x, edomid     = 0x%(2)08x ]

修改之後保存,然後執行如下命令:
cat rec.raw | xentrace_format formats >rec.txt
這個命令執行需要一些時間,慢慢等待會。。。

完成之後查看我們生成的rec.txt文件,查找tickle,如果可以看到類似如下的記錄:
14200 CPU0  519304896957 (+    1183)  do_tickle          [ domid = 0x00007fff, edomid = 0x00000000       ]

congratulations! ^-^
by spri1987 2010-6-22
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章