diff options
author | William Cohen <wcohen@localhost.localdomain> | 2008-04-24 12:20:13 -0400 |
---|---|---|
committer | William Cohen <wcohen@localhost.localdomain> | 2008-04-24 12:20:13 -0400 |
commit | 7f79ea13a0f64573ce13353257d322ae49ef0c27 (patch) | |
tree | 60de8da5af4c2bcc26abfb9430fdca66bdc20b98 /testsuite/systemtap.examples/small_demos | |
parent | f90f92615df6ff2a62282359281889597e5dbf17 (diff) | |
download | systemtap-steved-7f79ea13a0f64573ce13353257d322ae49ef0c27.tar.gz systemtap-steved-7f79ea13a0f64573ce13353257d322ae49ef0c27.tar.xz systemtap-steved-7f79ea13a0f64573ce13353257d322ae49ef0c27.zip |
Move examples to testsuite/systemtap.examples
Diffstat (limited to 'testsuite/systemtap.examples/small_demos')
16 files changed, 486 insertions, 0 deletions
diff --git a/testsuite/systemtap.examples/small_demos/ansi_colors.stp b/testsuite/systemtap.examples/small_demos/ansi_colors.stp new file mode 100755 index 00000000..0d9d7c47 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/ansi_colors.stp @@ -0,0 +1,21 @@ +#! /usr/bin/env stap + +probe begin { + printf("a \\ b |"); + for (c = 40; c < 48; c++) + printf(" %d ", c); + printf("\12"); + for (l = 0; l < 71; l++) + printf("-"); + printf("\12"); + + for (r = 30; r < 38; r++) + for (t = 0; t < 2; t++) { + printf("%d |", r); + for (c = 40; c < 48; c++) + printf("\033[%d;%d%s %s \033[0;0m", + r, c, !t ? "m" : ";1m", !t ? "Normal" : "Bold "); + printf("\12"); + } + exit(); +} diff --git a/testsuite/systemtap.examples/small_demos/click.wav b/testsuite/systemtap.examples/small_demos/click.wav Binary files differnew file mode 100644 index 00000000..8214b229 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/click.wav diff --git a/testsuite/systemtap.examples/small_demos/close.stp b/testsuite/systemtap.examples/small_demos/close.stp new file mode 100755 index 00000000..7ba2a036 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/close.stp @@ -0,0 +1,14 @@ +#!/usr/bin/env stap + +probe syscall.close { + printf("%s: %s(%s) = ", execname(), name, argstr) +} + +probe syscall.close.return { + printf("%s\n", returnstr(returnp)) +} + +probe end { + printf("DONE\n") +} + diff --git a/testsuite/systemtap.examples/small_demos/demo_script.txt b/testsuite/systemtap.examples/small_demos/demo_script.txt new file mode 100644 index 00000000..f3166a49 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/demo_script.txt @@ -0,0 +1,102 @@ +> cd /root/systemtap + +A systemtap script can be as simple as a single line. For example, +the following script places a probepoint on the kernel sys_read() +function and prints all callers with the function's arguments. + +>stap -e 'probe syscall.open {printf("%s: %s\n", execname(), argstr)}' + +Most scripts are a bit longer. (show top.stp) +This script sets a probepoint on all kernel functions beginning with "sys_". +When the probepoint is hit, it increments an entry in the map +(or associative array) "syscalls" with the key "probefunc()" which returns +the name of the function that was triggered. For example, "sys_read". + +There is a timer that is triggered every 5000ms or 5 seconds. That timer +calls the function print_top(). print_top() sorts the syscalls map +and prints the top 20 entries. Then it clears the map. + +> ./top.stp + +(after stopping "top" go ahead and enter "./sys.stp". It takes a minute +to load this script. Diplay the source in another window and talk +while it is loading.) + +The "top" script looked only at the functions called. If we want more +detail about the functions, we can use systemtap to examine their local +arguments and variables. However that would be difficult because each +system call has different parameters. The Syscall Tapset solves +this problem. To use it, we set probe points using the syntax "syscall.name" +instead of kernel.function("sys_name"). The Syscall Tapset provides three +defined variables we can use: +name - the name of the function +argstr - on function entry, a formatted string containing the arguments +retstr - on function exit, the return value and possibly error code + +In this example, we filter out programs named "staprun" because this is +part of the systemtap infrastructure. (It may be filtered out +automatically in the future.) + +The next example shows how you can use systemtap to focus on +specific programs or pids. (show prof.stp) + +Like the "top" example, this script places probes on all kernel +functions starting with "sys_". Only the probepoint also checks to see +if the tid/pid matches the one returned by "target()". We'll show how +the target pid is set later. + +Unlike the previous examples, this script sets a probe point on all the +system call returns. When triggered, this probepoint computes the elapsed +time since the function entry. + +To run this script, we must give it a pid to use for the target, or a +program to run, in which case target will be its pid. + +> ./prof.stp -c "top -n5" + +-------------------------------- + +Systemtap can also run in an unsafe mode where you can give +it arbitrary C code to run at probepoints, or modify kernel variables +and structures. This is very dangerous so only experts with root access will +ever be permitted to do this. + +(show keyhack.stp) + +The next example will modify the local variable "keycode" in the "kdb_keycode" +function in the kernel driver. We indicate it is a local variable by putting +a dollar sign before the name. + +./keyhack.stp + +(prints error message) + +To tell systemtap we really want to run this script, we must use the "-g" flag. + +./keyhack.stp -g + +(type some keys. "m" should display as "b" in every window) + +This example is not something you would normally want to do. There are +far better ways to remap a keyboard. What it demonstartes is that Systemtap +can modify variables in a running kernel. + +(show kmalloc.stp) +This next script shows the kind of statistics systemtap can collect. +It collects information about kernel allocations. + +> ./kmalloc.stp + +Now we can refine this further +(show kmalloc2.stp) + +Remember in some previous examples, we used maps or associative arrays. Maps can contain +statistics too. So we have enhanced the previous script to collect statistics per +program name. The output might be large so we'll redirect it to a file. + +> ./kmalloc2.stp > out + +(runs for 10 seconds) + +> more out + diff --git a/testsuite/systemtap.examples/small_demos/fileopen.stp b/testsuite/systemtap.examples/small_demos/fileopen.stp new file mode 100755 index 00000000..c1298f9c --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/fileopen.stp @@ -0,0 +1,24 @@ +#! /usr/bin/env stap + +# +# fileopen.stp +# +# This is based on dtrace script from +# http://www.gnome.org/~gman/blog/2006/Jan +# +# stap fileopen.stp -c "zenity --about" +# or +# ./fileopen.stp -c "program or script" + +global opens + +probe syscall.open { + if (target() == pid()) opens[filename] ++ +} + +probe end { + foreach([name] in opens+) { + printf("%-70s%5d\n", name, opens[name]) + } +} + diff --git a/testsuite/systemtap.examples/small_demos/key.stp b/testsuite/systemtap.examples/small_demos/key.stp new file mode 100755 index 00000000..6d2d6c3f --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/key.stp @@ -0,0 +1,22 @@ +#! /usr/bin/env stap + +# Useless, but amusing. Based on an idea I saw on a +# dtrace site. (wav files are from emacs). + +// KEY_ENTER = 28 +probe kernel.function("kbd_event") { + if ($event_type == 1 && $value) { + if ($event_code == 28) + system("play return.wav &> /dev/null") + else + system("play click.wav &> /dev/null") + } +} + +probe begin { + printf("TYPEWRITER ON\n") +} + +probe end { + printf("DONE\n") +} diff --git a/testsuite/systemtap.examples/small_demos/keyhack.stp b/testsuite/systemtap.examples/small_demos/keyhack.stp new file mode 100755 index 00000000..3137baad --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/keyhack.stp @@ -0,0 +1,15 @@ +#! /usr/bin/env stap + +# This is not useful, but it demonstrates that +# Systemtap can modify variables in a running kernel. + +# Usage: ./keyhack.stp -g + +probe kernel.function("kbd_event") { + # Changes 'm' to 'b' . + if ($event_code == 50) $event_code = 48 +} + +probe end { + printf("\nDONE\n") +} diff --git a/testsuite/systemtap.examples/small_demos/kmalloc.stp b/testsuite/systemtap.examples/small_demos/kmalloc.stp new file mode 100755 index 00000000..9157928d --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/kmalloc.stp @@ -0,0 +1,22 @@ +#! /usr/bin/env stap + +# Using statistics to examine kernel memory allocations + +global kmalloc + +probe kernel.function("__kmalloc") { + kmalloc <<< $size +} + +# Exit after 10 seconds +probe timer.ms(10000) { exit () } + +probe end { + printf("Count: %d allocations\n", @count(kmalloc)) + printf("Sum: %d Kbytes\n", @sum(kmalloc)/1000) + printf("Average: %d bytes\n", @avg(kmalloc)) + printf("Min: %d bytes\n", @min(kmalloc)) + printf("Max: %d bytes\n", @max(kmalloc)) + print("\nAllocations by size in bytes\n") + print(@hist_log(kmalloc)) +} diff --git a/testsuite/systemtap.examples/small_demos/kmalloc2.stp b/testsuite/systemtap.examples/small_demos/kmalloc2.stp new file mode 100755 index 00000000..2622dd2f --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/kmalloc2.stp @@ -0,0 +1,26 @@ +#! /usr/bin/env stap + +# Using statistics and maps to examine kernel memory allocations + +global kmalloc + +probe kernel.function("__kmalloc") { + kmalloc[execname()] <<< $size +} + +# Exit after 10 seconds +probe timer.ms(10000) { exit () } + +probe end { + foreach ([name] in kmalloc) { + printf("Allocations for %s\n", name) + printf("Count: %d allocations\n", @count(kmalloc[name])) + printf("Sum: %d Kbytes\n", @sum(kmalloc[name])/1000) + printf("Average: %d bytes\n", @avg(kmalloc[name])) + printf("Min: %d bytes\n", @min(kmalloc[name])) + printf("Max: %d bytes\n", @max(kmalloc[name])) + print("\nAllocations by size in bytes\n") + print(@hist_log(kmalloc[name])) + printf("-------------------------------------------------------\n\n"); + } +} diff --git a/testsuite/systemtap.examples/small_demos/proc_snoop.stp b/testsuite/systemtap.examples/small_demos/proc_snoop.stp new file mode 100755 index 00000000..24499b4b --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/proc_snoop.stp @@ -0,0 +1,55 @@ +#!/usr/bin/env stap + +global start_ts + +probe begin { + start_ts = gettimeofday_us() + printf("%12s %5s %5s %-16s ACTION\n", + "TIMESTAMP", "PID", "TID", "EXECNAME") +} + +function report(action:string) { + printf("%12d %5d %5d %-16s %s\n", gettimeofday_us() - start_ts, + pid(), tid(), execname(), action) +} + +function id:string(task:long) { + return sprintf("p:%d t:%d n:%s", task_pid(task), task_tid(task), + task_execname(task)) +} + +probe process.create { + report(sprintf("create %s", id(task))) +} + +probe process.start { + report("start") +} + +probe process.exec { + report(sprintf("exec %s", filename)) +} + +probe process.exec_complete { + if (success) + report("exec success") + else + report(sprintf("exec failed %d (%s)", errno, errno_str(errno))) +} + +probe process.exit { + report(sprintf("exit %d", code)) +} + +probe process.release { + report(sprintf("remove %s", id(task))) +} + +probe signal.send { + report(sprintf("sigsend %d (%s) to %s%s", sig, sig_name, id(task), + shared? " [SHARED]" : "")) +} + +probe signal.handle { + report(sprintf("sighandle %d (%s)", sig, sig_name)) +} diff --git a/testsuite/systemtap.examples/small_demos/prof.stp b/testsuite/systemtap.examples/small_demos/prof.stp new file mode 100755 index 00000000..389f743a --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/prof.stp @@ -0,0 +1,35 @@ +#!/usr/bin/env stap + +# This is an example of profiling a specific command or pid. +# It works by recording the time when a system call is entered +# exited. + +# Usage: prof.stp -c "top -n5" +# Will start up "top" and after 5 iterations, will exit. +# +# Usage: prof.stp -x 3323 +# Will profile pid 3323 until it ^c is hit. +# + +probe kernel.function("sys_*").call { + if (target() == tid()) + calltime[tid()] = gettimeofday_us() +} + +probe kernel.function("sys_*").return { + if (target() != tid()) next + now = gettimeofday_us() + c = calltime[tid()] + if (!c) next + ttime[probefunc()] <<< now - c + delete calltime[tid()] +} + +probe end { + printf("\n") + foreach (x in ttime) + printf("%-20s\tcalls:%6d\tavg time (us):%5d\ttotal(us):%7d\n", + x, @count(ttime[x]), @avg(ttime[x]), @sum(ttime[x])) +} + +global calltime, ttime diff --git a/testsuite/systemtap.examples/small_demos/return.wav b/testsuite/systemtap.examples/small_demos/return.wav Binary files differnew file mode 100644 index 00000000..20f978cc --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/return.wav diff --git a/testsuite/systemtap.examples/small_demos/rwtiming.stp b/testsuite/systemtap.examples/small_demos/rwtiming.stp new file mode 100755 index 00000000..d570c581 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/rwtiming.stp @@ -0,0 +1,74 @@ +#! /usr/bin/env stap +# rwtiming.stp +# +# This is a simple example to track the amount of time +# spent doing reads and writes for the various programs running on the +# system. + +probe begin { log("starting probe") } + +global names, opens, reads, writes +global entry_opens, entry_reads, entry_writes +global time_opens, time_reads, time_writes + +probe kernel.function("sys_open") { + t=gettimeofday_us(); p=pid(); e=execname(); + names[e]=1 + opens[e] ++ # plain integer + entry_opens[p] = t; +} + +probe kernel.function("sys_open").return { + t=gettimeofday_us(); p=pid(); e=execname(); + time_opens[e] <<< t - entry_opens[p]; +} + +probe kernel.function("sys_read") { + t= gettimeofday_us(); p =pid(); e=execname(); + names[e]=1 + reads[e] <<< $count # statistics + entry_reads[p] = t; +} + +probe kernel.function("sys_read").return { + t=gettimeofday_us(); p=pid(); e=execname(); + time_reads[e] <<< t - entry_reads[p]; +} + +probe kernel.function("sys_write") { + t=gettimeofday_us(); p=pid(); e=execname(); + names[e]=1 + writes[e] <<< $count # statistics + entry_writes[p] = t; +} + +probe kernel.function("sys_write").return { + t = gettimeofday_us(); p = pid(); e=execname(); + time_writes[e] <<< t - entry_writes[p]; +} + +probe end { + foreach(name+ in names) { # sort by names + printf ("process: %s\n", name) + if (opens[name]) { + printf ("opens n=%d\n", opens[name]) + print (@hist_log(time_opens[name])) + } + if (@count(reads[name])) { + printf ("reads n=%d, sum=%d, avg=%d\n", + @count(reads[name]), # extracting stat results + @sum(reads[name]), + @avg(reads[name])) + print ("read timing distribution\n") + print (@hist_log(time_reads[name])) + } + if (@count(writes[name])) { + printf ("writes n=%d, sum=%d, avg=%d\n", + @count(writes[name]), # extracting stat results + @sum(writes[name]), + @avg(writes[name])) + print ("write timing distribution\n") + print (@hist_log(time_writes[name])) + } + } +} diff --git a/testsuite/systemtap.examples/small_demos/sched_snoop.stp b/testsuite/systemtap.examples/small_demos/sched_snoop.stp new file mode 100755 index 00000000..623643dd --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/sched_snoop.stp @@ -0,0 +1,35 @@ +#!/usr/bin/env stap + +global start_ts + +probe begin { + start_ts = gettimeofday_us() + printf("%12s %3s %5s %5s %-16s ACTION\n", + "TIMESTAMP", "CPU", "PID", "TID", "EXECNAME") +} + +function report(action:string) { + printf("%3d %12d %5d %5d %-16s %s\n", + gettimeofday_us() - start_ts, cpu(), + pid(), tid(), execname(), action) +} + +probe scheduler.cpu_off { + report(sprintf("cpu_off%s", idle? " [idle]" : "")) +} + +probe scheduler.cpu_on { + report(sprintf("cpu_on%s", idle? " [idle]" : "")) +} + +probe scheduler.tick { + report(sprintf("tick%s", idle? " [idle]" : "")) +} + +probe scheduler.migrate ? { + report("migrate") +} + +probe scheduler.balance ? { + report("balance") +} diff --git a/testsuite/systemtap.examples/small_demos/sys.stp b/testsuite/systemtap.examples/small_demos/sys.stp new file mode 100755 index 00000000..2df20bc3 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/sys.stp @@ -0,0 +1,17 @@ +#!/usr/bin/env stap + +# print all system calls on the system + +probe syscall.* { + if (execname() != "staprun") + printf("%s: %s (%s) = ", execname(), name, argstr) +} + +probe syscall.*.return { + if (execname() != "staprun") + printf("%s\n", retstr) +} + +probe end { + printf("\n") +} diff --git a/testsuite/systemtap.examples/small_demos/top.stp b/testsuite/systemtap.examples/small_demos/top.stp new file mode 100755 index 00000000..b46b9940 --- /dev/null +++ b/testsuite/systemtap.examples/small_demos/top.stp @@ -0,0 +1,24 @@ +#!/usr/bin/env stap +# +# This script continuously lists the top 20 systemcalls on the system +# + +global syscalls + +function print_top () { + printf ("SYSCALL\t\t\t\tCOUNT\n") + foreach ([name] in syscalls- limit 20) + printf("%-20s\t\t%5d\n",name, syscalls[name]) + printf("--------------------------------------\n") + delete syscalls +} + +probe syscall.* { + syscalls[probefunc()]++ +} + +# print top syscalls every 5 seconds +probe timer.ms(5000) { + print_top () +} + |