show_delta使用

setenv mmcroot "/dev/mmcblk1p2 rootwait rw initcall_debug printk.time=1"

dmesg > kerneltime
scripts/ kerneltime > boot.svg
# printk.time=1 or CONFIG_PRINTK_TIME=y 
scripts/show_delta kerneltime > deltatime

bootgraph命令执行以后生成的boot.svg还可以,不过show_delta则匪夷所思,完全是将原始数据打印了一份还多了空行,deltatime的结果部分如下

[    0.002652] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=240000)

[    0.002689] CPU: Testing write buffer coherency: ok

[    0.002784] pid_max: default: 32768 minimum: 301

[    0.003227] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)

[    0.003269] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)

[    0.007276] cblist_init_generic: Setting adjustable number of callback queues.

当时以为是命令使用不正确, 搜索了一下,有的多了-b选项,也就是找一个有指定字符串的行开始处理,如scripts/show_delta -b Calibrating kerneltime > deltatime, 有点找不到方向了,乘兴而来,可能要败兴而归了,虽然这个功能用处不大,不过仍然想要弄明白,于是想看看脚本如何写的

usage: show_delta [<options>] <filename>

This program parses the output from a set of printk message lines which
have time data prefixed because the CONFIG_PRINTK_TIME option is set, or
the kernel command line option "time" is specified. When run with no
options, the time information is converted to show the time delta between
each printk line and the next.  When run with the '-b' option, all times
are relative to a single (base) point in time.

Options:
  -h            Show this usage help.
  -b <base>     Specify a base for time references.
                <base> can be a number or a string.
                If it is a string, the first message line
                which matches (at the beginning of the
                line) is used as the time reference.

ex: $ dmesg >timefile
    $ show_delta -b NET4 timefile

will show times relative to the line in the kernel output
starting with "NET4".

show_delta源码分析

show_delta代码很简单,仅仅100多行python代码,不过啥打印没有且有一段时间没有接触python了,还是需要静下心来看懂 main => convert_line(line, base_time)=>get_time(line),在get_time返回的加打印,尝试没有打印出来,函数一开始打印可以,所以问题在于string.split和string.atof中,疑问为啥执行有问题也不报错?

# returns a tuple containing the seconds and text for each message line
# seconds is returned as a float
# raise an exception if no timing data was found
def get_time(line):
        if line[0]!="[":
                raise ValueError

        # split on closing bracket
        (time_str, rest) = string.split(line[1:],']',1)
        time = string.atof(time_str)

        #print "time=", time
        return (time, rest)

通过搜索python3相关的函数实现,同时去掉'\n'

结果如下:

[0.002652 < 0.000082 >] Calibrating delay loop (skipped), value calculated using timer frequency.. 48.00 BogoMIPS (lpj=240000)
[0.002689 < 0.000037 >] CPU: Testing write buffer coherency: ok
[0.002784 < 0.000095 >] pid_max: default: 32768 minimum: 301
[0.003227 < 0.000443 >] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[0.003269 < 0.000042 >] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
[0.007276 < 0.004007 >] cblist_init_generic: Setting adjustable number of callback queues.
[0.007307 < 0.000031 >] cblist_init_generic: Setting shift to 0 and lim to 1.
[0.007564 < 0.000257 >] cblist_init_generic: Setting adjustable number of callback queues.
[0.007579 < 0.000015 >] cblist_init_generic: Setting shift to 0 and lim to 1.
(time_str, rest) = string.split(line[1:],']',1) ==>> time_str, rest = line[1:].split(']',1)
time = string.atof(time_str) ==> time=float(time_str)
rest = rest.rstrip('\n')

python相关

使用之前的show_delta,使用python2.7是可以的,因为我用的python3.10.12,才有问题 我们可以用dir(object)或者help(obj)在交互模式下查看到string对应的函数, 我们分别看看python2.7和python3.10.12的string情况 python3.10.12,可以看出没有string中已经没有split/find/atof等函数了, 而python2.7有的

Python 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import string
>>> help(string)

>>> dir(string)
['Formatter', 'Template', '_ChainMap', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_re', '_sentinel_dict', '_string', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'capwords', 'digits', 'hexdigits', 'octdigits', 'printable', 'punctuation', 'whitespace']
>>> help(string)

>>> string.split
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'string' has no attribute 'split'
>>> string.find
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'string' has no attribute 'find'
>>> string.atof
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'string' has no attribute 'atof'
>>> string.ascii_letters
'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
>>> string.capwords
<function capwords at 0x7710c5fee680>
>>> string.digits
'0123456789'
>>> string
<module 'string' from '/usr/lib/python3.10/string.py'>
>>> print(string)
<module 'string' from '/usr/lib/python3.10/string.py'>

python2.7

Python 2.7.18 (default, Oct 15 2023, 16:43:11) 
[GCC 11.4.0] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import string
>>> dir(string)
['Formatter', 'Template', '_TemplateMetaclass', '__builtins__', '__doc__', '__file__', '__name__', '__package__', '_float', '_idmap', '_idmapL', '_int', '_long', '_multimap', '_re', 'ascii_letters', 'ascii_lowercase', 'ascii_uppercase', 'atof', 'atof_error', 'atoi', 'atoi_error', 'atol', 'atol_error', 'capitalize', 'capwords', 'center', 'count', 'digits', 'expandtabs', 'find', 'hexdigits', 'index', 'index_error', 'join', 'joinfields', 'letters', 'ljust', 'lower', 'lowercase', 'lstrip', 'maketrans', 'octdigits', 'printable', 'punctuation', 'replace', 'rfind', 'rindex', 'rjust', 'rsplit', 'rstrip', 'split', 'splitfields', 'strip', 'swapcase', 'translate', 'upper', 'uppercase', 'whitespace', 'zfill']
>>> help(string)

>>> string.split
<function split at 0x7f842a07d6d0>
>>> string.split("hello]dd",']',1)
['hello', 'dd']
>>> string.atof("0.12308")
0.12308
>>> string
<module 'string' from '/usr/lib/python2.7/string.pyc'>

关于string相关,网上的信息如下:

string.ato* were deprecated in python 2.0, and removed >= 3.0. I replaced them with float()/int(), where appropriate.

show_delta 修改完全版

完整的代码如下:

#!/usr/bin/env python
# SPDX-License-Identifier: GPL-2.0-only
#
# show_deltas: Read list of printk messages instrumented with
# time data, and format with time deltas.
#
# Also, you can show the times relative to a fixed point.
#
# Copyright 2003 Sony Corporation
#

import sys
import string

def usage():
	print ("""usage: show_delta [<options>] <filename>

This program parses the output from a set of printk message lines which
have time data prefixed because the CONFIG_PRINTK_TIME option is set, or
the kernel command line option "time" is specified. When run with no
options, the time information is converted to show the time delta between
each printk line and the next.  When run with the '-b' option, all times
are relative to a single (base) point in time.

Options:
  -h            Show this usage help.
  -b <base>	Specify a base for time references.
		<base> can be a number or a string.
		If it is a string, the first message line
		which matches (at the beginning of the
		line) is used as the time reference.

ex: $ dmesg >timefile
    $ show_delta -b NET4 timefile

will show times relative to the line in the kernel output
starting with "NET4".
""")
	sys.exit(1)

# returns a tuple containing the seconds and text for each message line
# seconds is returned as a float
# raise an exception if no timing data was found
def get_time(line):
	if line[0]!="[":
		raise ValueError

	# split on closing bracket
	#(time_str, rest) = string.split(line[1:],']',1)
    # time = string.atof(time_str)
	time_str, rest	= line[1:].split(']',1)
	time = float(time_str)
	rest = rest.rstrip('\n')

	return (time, rest)

# average line looks like:
# [    0.084282] VFS: Mounted root (romfs filesystem) readonly
# time data is expressed in seconds.useconds,
# convert_line adds a delta for each line
last_time = 0.0
def convert_line(line, base_time):
	global last_time

	try:
		(time, rest) = get_time(line)
	except:
		# if any problem parsing time, don't convert anything
		return line

	if base_time:
		# show time from base
		delta = time - base_time
	else:
		# just show time from last line
		delta = time - last_time
		last_time = time


	return ("[%5.6f < %5.6f >]" % (time, delta)) + rest

def main():
	base_str = ""
	filein = ""
	for arg in sys.argv[1:]:
		if arg=="-b":
			base_str = sys.argv[sys.argv.index("-b")+1]
		elif arg=="-h":
			usage()
		else:
			filein = arg

	if not filein:
		usage()

	try:
		lines = open(filein,"r").readlines()
	except:
		print ("Problem opening file: %s" % filein)
		sys.exit(1)

	if base_str:
		print ('base= "%s"' % base_str)
		# assume a numeric base.  If that fails, try searching
		# for a matching line.
		try:
			base_time = float(base_str)
		except:
			# search for line matching <base> string
			found = 0
			for line in lines:
				try:
					(time, rest) = get_time(line)
				except:
					continue
				if rest.find(base_str)==1:
					base_time = time
					found = 1
					# stop at first match
					break
			if not found:
				print ('Couldn\'t find line matching base pattern "%s"' % base_str)
				sys.exit(1)
	else:
		base_time = 0.0

	for line in lines:
		print (convert_line(line, base_time),)

main()

references:

  1. https://ioflood.com/blog/convert-string-to-float-python/
  2. https:///psychopy/psychopy/pull/1853