From e1d96810d0c2c1da6ec36eb81c642bcc6cf420c8 Mon Sep 17 00:00:00 2001 From: hunt Date: Mon, 20 Mar 2006 16:05:24 +0000 Subject: [PATCH] *** empty log message *** --- examples/{ => small_demos}/click.wav | Bin examples/small_demos/close.stp | 7 ++ examples/small_demos/demo_script.txt | 103 ++++++++++++++++++++++++++ examples/{ => small_demos}/key.stp | 6 +- examples/small_demos/keyhack.stp | 15 ++++ examples/small_demos/kmalloc.stp | 22 ++++++ examples/small_demos/kmalloc2.stp | 26 +++++++ examples/{ => small_demos}/prof.stp | 0 examples/{ => small_demos}/return.wav | Bin examples/small_demos/sys.stp | 17 +++++ examples/{ => small_demos}/top.stp | 0 runtime/transport/procfs.c | 6 +- 12 files changed, 197 insertions(+), 5 deletions(-) rename examples/{ => small_demos}/click.wav (100%) create mode 100755 examples/small_demos/close.stp create mode 100644 examples/small_demos/demo_script.txt rename examples/{ => small_demos}/key.stp (74%) create mode 100755 examples/small_demos/keyhack.stp create mode 100755 examples/small_demos/kmalloc.stp create mode 100755 examples/small_demos/kmalloc2.stp rename examples/{ => small_demos}/prof.stp (100%) rename examples/{ => small_demos}/return.wav (100%) create mode 100755 examples/small_demos/sys.stp rename examples/{ => small_demos}/top.stp (100%) diff --git a/examples/click.wav b/examples/small_demos/click.wav similarity index 100% rename from examples/click.wav rename to examples/small_demos/click.wav diff --git a/examples/small_demos/close.stp b/examples/small_demos/close.stp new file mode 100755 index 000000000..341667f8f --- /dev/null +++ b/examples/small_demos/close.stp @@ -0,0 +1,7 @@ +probe syscall.close { + printf("%s: %s(%s) = ", execname(), name, argstr) +} + +probe syscall.close.return { + printf("%s\n", returnstr(returnp)) +} diff --git a/examples/small_demos/demo_script.txt b/examples/small_demos/demo_script.txt new file mode 100644 index 000000000..40408c4d2 --- /dev/null +++ b/examples/small_demos/demo_script.txt @@ -0,0 +1,103 @@ +> cd /root/systemtap + +A systemtap script can be as simple as a simgle line. For example, +thge 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 script 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 Sycall 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 "stpd" 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/examples/key.stp b/examples/small_demos/key.stp similarity index 74% rename from examples/key.stp rename to examples/small_demos/key.stp index 6334cbbfb..0489524a7 100755 --- a/examples/key.stp +++ b/examples/small_demos/key.stp @@ -4,9 +4,9 @@ # dtrace site. (wav files are from emacs). // KEY_ENTER = 28 -probe kernel.function("kbd_keycode") { - if ($down) { - if ($keycode == 28) +probe kernel.function("kbd_event") { + if ($event_type == 1 && $value) { + if ($event_code == 28) system("play return.wav") else system("play click.wav") diff --git a/examples/small_demos/keyhack.stp b/examples/small_demos/keyhack.stp new file mode 100755 index 000000000..3137baad8 --- /dev/null +++ b/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/examples/small_demos/kmalloc.stp b/examples/small_demos/kmalloc.stp new file mode 100755 index 000000000..9157928da --- /dev/null +++ b/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/examples/small_demos/kmalloc2.stp b/examples/small_demos/kmalloc2.stp new file mode 100755 index 000000000..2622dd2f4 --- /dev/null +++ b/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/examples/prof.stp b/examples/small_demos/prof.stp similarity index 100% rename from examples/prof.stp rename to examples/small_demos/prof.stp diff --git a/examples/return.wav b/examples/small_demos/return.wav similarity index 100% rename from examples/return.wav rename to examples/small_demos/return.wav diff --git a/examples/small_demos/sys.stp b/examples/small_demos/sys.stp new file mode 100755 index 000000000..c25055dec --- /dev/null +++ b/examples/small_demos/sys.stp @@ -0,0 +1,17 @@ +#!/usr/bin/env stap + +# print all system calls on the system + +probe syscall.* { + if (execname() != "stpd") + printf("%s: %s (%s) = ", execname(), name, argstr) +} + +probe syscall.*.return { + if (execname() != "stpd") + printf("%s\n", retstr) +} + +probe end { + printf("\n") +} diff --git a/examples/top.stp b/examples/small_demos/top.stp similarity index 100% rename from examples/top.stp rename to examples/small_demos/top.stp diff --git a/runtime/transport/procfs.c b/runtime/transport/procfs.c index ec463c4c9..cbcc5239d 100644 --- a/runtime/transport/procfs.c +++ b/runtime/transport/procfs.c @@ -1,7 +1,7 @@ /* -*- linux-c -*- * * /proc transport and control - * Copyright (C) 2005 Red Hat Inc. + * Copyright (C) 2005, 2006 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -133,7 +133,9 @@ static int _stp_write (int type, void *data, int len) spin_lock(&_stp_ready_lock); if (!list_empty(&_stp_ready_q)) { bptr = (struct _stp_buffer *)_stp_ready_q.prev; - if (bptr->len + len <= STP_BUFFER_SIZE && bptr->type == type) { + if (bptr->len + len <= STP_BUFFER_SIZE + && type == STP_REALTIME_DATA + && bptr->type == STP_REALTIME_DATA) { memcpy (bptr->buf + bptr->len - 1, data, len); bptr->len += len - 1; spin_unlock(&_stp_ready_lock); -- 2.43.5