分类: LINUX
2010-02-03 09:54:35
#!/usr/bin/env python
# by Mark Williamson, (C) 2004 Intel Research
# Program for reformatting trace buffer output according to user-supplied rules
import re, sys, string, signal, struct, os, getopt
def usage():
print >> sys.stderr, \
"Usage: " + sys.argv[0] + """ defs-file
Parses trace data in binary format, as output by Xentrace and
reformats it according to the rules in a file of definitions. The
rules in this file should have the format ({ and } show grouping
and are not part of the syntax):
{event_id}{whitespace}{text format string}
The textual format string may include format specifiers, such as:
%(cpu)d, %(tsc)d, %(event)d, %(1)d, %(2)d, %(3)d, %(4)d, ...
[ the 'd' format specifier outputs in decimal, alternatively 'x'
will output in hexadecimal and 'o' will output in octal ]
Which correspond to the CPU number, event ID, timestamp counter and
the 7 data fields from the trace record. There should be one such
rule for each type of event.
Depending on your system and the volume of trace buffer data,
this script may not be able to keep up with the output of xentrace
if it is piped directly. In these circumstances you should have
xentrace output to a file for processing off-line.
"""
sys.exit(1)
def read_defs(defs_file):
defs = {}
fd = open(defs_file)
reg = re.compile('(\S+)\s+(\S.*)') // 对正则表达式的处理使用re模块
while True:
line = fd.readline()
if not line:
break
if line[0] == '#' or line[0] == '\n':
continue
m = reg.match(line)
if not m: print >> sys.stderr, "Bad format file" ; sys.exit(1)
defs[str(eval(m.group(1)))] = m.group(2) // 以EVENTID的十进制做key
return defs
def sighand(x,y):
global interrupted
interrupted = 1
##### Main code
mhz = 0
if len(sys.argv) < 2:
usage()
try:
opts, arg = getopt.getopt(sys.argv[1:], "c:" )
for opt in opts: // 获得的options信息存放到opts
if opt[0] == '-c' : mhz = int(opt[1])
except getopt.GetoptError: // getopt.getopt需要处理getopt.GetoptError异常
usage()
signal.signal(signal.SIGTERM, sighand)
signal.signal(signal.SIGHUP, sighand)
signal.signal(signal.SIGINT, sighand)
interrupted = 0
try:
defs = read_defs(arg[0]) // arg数组为剩余命令行参数列表
except IOError, exn:
print exn
sys.exit(1)
# structure of trace record (as output by xentrace):
# HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I) D6(I) D7(I)
#
# HDR consists of EVENT:28:, n_data:3:, tsc_in:1: // 参考struct t_rec
# EVENT means Event ID
# n_data means number of data (like D1, D2, ...)
# tsc_in means TSC data exists(1) or not(0).
# if tsc_in == 0, TSC(Q) does not exists.
#
# CPU ID exists on trace data of EVENT=0x0001f003
#
HDRREC = "I" // ui
TSCREC = "Q" // ull
D1REC = "I"
D2REC = "II"
D3REC = "III"
D4REC = "IIII"
D5REC = "IIIII"
D6REC = "IIIIII"
D7REC = "IIIIIII"
last_tsc = [0]
TRC_TRACE_IRQ = 0x1f004
NR_VECTORS = 256
irq_measure = [{'count':0, 'tot_cycles':0, 'max_cycles':0}] * NR_VECTORS
i=0
while not interrupted: // 如果没有信号打断
try:
i=i+1
line = sys.stdin.read(struct.calcsize(HDRREC)) // 读入4个字节
if not line:
break
event = struct.unpack(HDRREC, line)[0] // 将字节流转换为python数据类型
n_data = event >> 28 & 0x7 // 数据个数
tsc_in = event >> 31 // 时间戳flag
d1 = 0
d2 = 0
d3 = 0
d4 = 0
d5 = 0
d6 = 0
d7 = 0
tsc = 0
if tsc_in == 1:
line = sys.stdin.read(struct.calcsize(TSCREC))
if not line:
break
tsc = struct.unpack(TSCREC, line)[0]
if n_data == 1:
line = sys.stdin.read(struct.calcsize(D1REC))
if not line:
break
d1 = struct.unpack(D1REC, line)[0]
if n_data == 2:
line = sys.stdin.read(struct.calcsize(D2REC))
if not line:
break
(d1, d2) = struct.unpack(D2REC, line)
if n_data == 3:
line = sys.stdin.read(struct.calcsize(D3REC))
if not line:
break
(d1, d2, d3) = struct.unpack(D3REC, line)
if n_data == 4:
line = sys.stdin.read(struct.calcsize(D4REC))
if not line:
break
(d1, d2, d3, d4) = struct.unpack(D4REC, line)
if n_data == 5:
line = sys.stdin.read(struct.calcsize(D5REC))
if not line:
break
(d1, d2, d3, d4, d5) = struct.unpack(D5REC, line)
if n_data == 6:
line = sys.stdin.read(struct.calcsize(D6REC))
if not line:
break
(d1, d2, d3, d4, d5, d6) = struct.unpack(D6REC, line)
if n_data == 7:
line = sys.stdin.read(struct.calcsize(D7REC))
if not line:
break
(d1, d2, d3, d4, d5, d6, d7) = struct.unpack(D7REC, line)
# Event field is 28bit of 'uint32_t' in header, not 'long'.
event &= 0x0fffffff
if event == 0x1f003: // TRC_TRACE_CPU_CHANGE
cpu = d1
if event == TRC_TRACE_IRQ:
# IN - d1:vector, d2:tsc_in, d3:tsc_out
# OUT - d1:vector, d2:count, d3:tot_cycles, d4:max_cycles
tsc_diff = d3 - d2
if tsc_diff < 0:
break
irq_measure[d1]['count'] += 1
irq_measure[d1]['tot_cycles'] += tsc_diff
if irq_measure[d1]['max_cycles'] < tsc_diff:
irq_measure[d1]['max_cycles'] = tsc_diff
d2 = irq_measure[d1]['count']
d3 = irq_measure[d1]['tot_cycles']
d4 = irq_measure[d1]['max_cycles']
#tsc = (tscH<<32) | tscL
#print i, tsc
if cpu >= len(last_tsc):
last_tsc += [0] * (cpu - len(last_tsc) + 1)
elif tsc < last_tsc[cpu] and tsc_in == 1:
print "TSC stepped backward cpu %d ! %d %d" % (cpu,tsc,last_tsc[cpu])
# provide relative TSC
if last_tsc[cpu] > 0 and tsc_in == 1:
reltsc = tsc - last_tsc[cpu]
else:
reltsc = 0
if tsc_in == 1:
last_tsc[cpu] = tsc
if mhz:
tsc = tsc / (mhz*1000000.0)
args = {'cpu' : cpu,
'tsc' : tsc,
'event' : event,
'reltsc': reltsc,
'1' : d1,
'2' : d2,
'3' : d3,
'4' : d4,
'5' : d5,
'6' : d6,
'7' : d7 }
try:
if defs.has_key(str(event)):
print defs[str(event)] % args
-------------------------------------------------------------------------------------------------------------------------------------
defs中得到此EVENTID对应的格式化字符串,例print "CPU%(cpu)d %(tsc)d %(1)d" % args
所以,输出格式文件中的每一行,实际是python对散列表里的元素进行输出时,采用的一种格式
-------------------------------------------------------------------------------------------------------------------------------------
else:
if defs.has_key(str(0)): print defs[str(0)] % args
except TypeError:
if defs.has_key(str(event)):
print defs[str(event)]
print args
else:
if defs.has_key(str(0)):
print defs[str(0)]
print args
except IOError, struct.error: sys.exit()
/* This structure represents a single trace buffer record. */
struct t_rec {
uint32_t event:28;
uint32_t extra_u32:3; /* # entries in trailing extra_u32[] array */
uint32_t cycles_included:1; /* u.cycles or u.no_cycles? */
union {
struct {
uint32_t cycles_lo, cycles_hi; /* cycle counter timestamp */
uint32_t extra_u32[7]; /* event data items */
} cycles;
struct {
uint32_t extra_u32[7]; /* event data items */
} nocycles;
} u;
};