Linux SystemTap Beginners Guide
Linux SystemTap Beginners Guide
This documentation is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA For more details see the file COPYING in the source distribution of Linux.
Preface v 1. Document Conventions ................................................................................................... v 1.1. Typographic Conventions ...................................................................................... v 1.2. Pull-quote Conventions ........................................................................................ vi 1.3. Notes and Warnings ........................................................................................... vii 2. We Need Feedback! ..................................................................................................... viii 1. Introduction 1 1.1. Documentation Goals ................................................................................................... 1 1.2. SystemTap Capabilities ................................................................................................ 1 2. Using SystemTap 2.1. Installation and Setup ................................................................................................... 2.1.1. Installing SystemTap .......................................................................................... 2.1.2. Installing Required Kernel Information RPMs ....................................................... 2.1.3. Initial Testing ..................................................................................................... 2.2. Generating Instrumentation for Other Computers ........................................................... 2.3. Running SystemTap Scripts .......................................................................................... 3 3 3 3 4 5 7
3. Understanding How SystemTap Works 9 3.1. Architecture .................................................................................................................. 9 3.2. SystemTap Scripts ....................................................................................................... 9 3.2.1. Event .............................................................................................................. 11 3.2.2. Systemtap Handler/Body .................................................................................. 13 3.3. Basic SystemTap Handler Constructs .......................................................................... 16 3.3.1. Variables ......................................................................................................... 16 3.3.2. Conditional Statements .................................................................................... 17 3.3.3. Command-Line Arguments ............................................................................... 19 3.4. Associative Arrays ...................................................................................................... 19 3.5. Array Operations in SystemTap ................................................................................... 20 3.5.1. Assigning an Associated Value ......................................................................... 20 3.5.2. Reading Values From Arrays ........................................................................... 20 3.5.3. Incrementing Associated Values ....................................................................... 21 3.5.4. Processing Multiple Elements in an Array .......................................................... 21 3.5.5. Clearing/Deleting Arrays and Array Elements .................................................... 22 3.5.6. Using Arrays in Conditional Statements ............................................................ 23 3.5.7. Computing for Statistical Aggregates ................................................................ 24 3.6. Tapsets ...................................................................................................................... 26 4. Useful SystemTap Scripts 4.1. Network ..................................................................................................................... 4.1.1. Network Profiling ............................................................................................. 4.1.2. Tracing Functions Called in Network Socket Code ............................................. 4.1.3. Monitoring Incoming TCP Connections .............................................................. 4.1.4. Monitoring Network Packets Drops in Kernel ..................................................... 4.2. Disk ........................................................................................................................... 4.2.1. Summarizing Disk Read/Write Traffic ................................................................ 4.2.2. Tracking I/O Time For Each File Read or Write ................................................. 4.2.3. Track Cumulative IO ........................................................................................ 4.2.4. I/O Monitoring (By Device) ............................................................................... 4.2.5. Monitoring Reads and Writes to a File .............................................................. 4.2.6. Monitoring Changes to File Attributes ................................................................ 4.3. Profiling ..................................................................................................................... 27 27 27 29 30 30 32 32 34 36 38 39 40 40
iii
4.3.1. Counting Function Calls Made .......................................................................... 4.3.2. Call Graph Tracing .......................................................................................... 4.3.3. Determining Time Spent in Kernel and User Space ............................................ 4.3.4. Monitoring Polling Applications ......................................................................... 4.3.5. Tracking Most Frequently Used System Calls .................................................... 4.3.6. Tracking System Call Volume Per Process ........................................................ 4.4. Identifying Contended User-Space Locks .....................................................................
40 41 43 44 47 48 50
5. Understanding SystemTap Errors 53 5.1. Parse and Semantic Errors ......................................................................................... 53 5.2. Run Time Errors and Warnings ................................................................................... 55 6. References A. Revision History Index 57 59 61
iv
Preface
1. Document Conventions
This manual uses several conventions to highlight certain words and phrases and draw attention to specific pieces of information. In PDF and paper editions, this manual uses typefaces drawn from the Liberation Fonts set. The Liberation Fonts set is also used in HTML editions if the set is installed on your system. If not, alternative but equivalent typefaces are displayed. Note: Red Hat Enterprise Linux 5 and later includes the Liberation Fonts set by default.
1
https://fedorahosted.org/liberation-fonts/
Preface
Choose System > Preferences > Mouse from the main menu bar to launch Mouse Preferences. In the Buttons tab, click the Left-handed mouse check box and click Close to switch the primary mouse button from the left to the right (making the mouse suitable for use in the left hand). To insert a special character into a gedit file, choose Applications > Accessories > Character Map from the main menu bar. Next, choose Search > Find from the Character Map menu bar, type the name of the character in the Search field and click Next. The character you sought will be highlighted in the Character Table. Double-click this highlighted character to place it in the Text to copy field and then click the Copy button. Now switch back to your document and choose Edit > Paste from the gedit menu bar. The above text includes application names; system-wide menu names and items; application-specific menu names; and buttons and text found within a GUI interface, all presented in proportional bold and all distinguishable by context. Note the > shorthand used to indicate traversal through a menu and its sub-menus. This avoids difficult-to-follow phrasing such as 'Select Mouse from the Preferences sub-menu in the System menu of the main menu bar'. Mono-spaced Bold Italic or Proportional Bold Italic Whether mono-spaced bold or proportional bold, the addition of italics indicates replaceable or variable text. Italics denotes text you do not input literally or displayed text that changes depending on circumstance. For example: To connect to a remote machine using ssh, type ssh username@domain.name at a shell prompt. If the remote machine is example.com and your username on that machine is john, type ssh john@example.com. The mount -o remount file-system command remounts the named file system. For example, to remount the /home file system, the command is mount -o remount /home. To see the version of a currently installed package, use the rpm -q package command. It will return a result as follows: package-version-release. Note the words in bold italics above username, domain.name, file-system, package, version and release. Each word is a placeholder, either for text you enter when issuing a command or for text displayed by the system. Aside from standard usage for presenting the title of a work, italics denotes the first use of a new and important term. For example: When the Apache HTTP Server accepts requests, it dispatches child processes or threads to handle them. This group of child processes or threads is known as a server-pool. Under Apache HTTP Server 2.0, the responsibility for creating and maintaining these server-pools has been abstracted to a group of modules called Multi-Processing Modules (MPMs). Unlike other modules, only one module from the MPM group can be loaded by the Apache HTTP Server.
vi
Source-code listings are also set in mono-spaced roman but add syntax highlighting as follows:
package org.jboss.book.jca.ex1; import javax.naming.InitialContext; public class ExClient { public static void main(String args[]) throws Exception { InitialContext iniCtx = new InitialContext(); Object ref = iniCtx.lookup("EchoBean"); EchoHome home = (EchoHome) ref; Echo echo = home.create(); System.out.println("Created Echo"); System.out.println("Echo.echo('Hello') = " + echo.echo("Hello")); } }
Note
Notes are tips, shortcuts or alternative approaches to the task at hand. Ignoring a note should have no negative consequences, but you might miss out on a trick that makes your life easier.
Important
Important boxes detail things that are easily missed: configuration changes that only apply to the current session, or services that need restarting before an update will apply. Ignoring a box labeled 'Important' won't cause data loss but may cause irritation and frustration.
Warning
Warnings should not be ignored. Ignoring warnings will most likely cause data loss.
vii
Preface
2. We Need Feedback!
If you find a typographical error in this manual, or if you have thought of a way to make this manual better, we would love to hear from you! Please submit a report in Bugzilla: http://bugzilla.redhat.com/ bugzilla/ against the product Red_Hat_Enterprise_Linux 5. When submitting a bug report, be sure to mention the manual's identifier: SystemTap_Beginners_Guide If you have a suggestion for improving the documentation, try to be as specific as possible when describing it. If you have found an error, please include the section number and some of the surrounding text so we can find it easily.
viii
Chapter 1.
Introduction
SystemTap is a tracing and probing tool that allows users to study and monitor the activities of the operating system (particularly, the kernel) in fine detail. It provides information similar to the output of tools like netstat, ps, top, and iostat; however, SystemTap is designed to provide more filtering and analysis options for collected information.
Limitations
The current iteration of SystemTap allows for a multitude of options when probing kernel-space events. However, SystemTap's ability to probe user-space events is quite limited. At present, the
Chapter 1. Introduction
developmental efforts of the SystemTap community are geared towards improving SystemTap's userspace probing capabilities.
Chapter 2.
Using SystemTap
This chapter instructs users how to install SystemTap, and provides an introduction on how to run SystemTap scripts.
Important
Many users confuse -debuginfo with -debug. Remember that the deployment of SystemTap requires the installation of the -debuginfo package of the kernel, not the debug version of the kernel.
uname -r
For example, if you wish to use SystemTap on kernel version 2.6.18-53.el5 on an i686 machine, then you would need to download and install the following RPMs: kernel-debuginfo-2.6.18-53.1.13.el5.i686.rpm kernel-debuginfo-common-2.6.18-53.1.13.el5.i686.rpm kernel-devel-2.6.18-53.1.13.el5.i686.rpm
Important
The version, variant, and architecture of the -devel, -debuginfo and -debuginfocommon packages must match the kernel you wish to probe with SystemTap exactly. The easiest way to install the required kernel information packages is through yum install and debuginfo-install. debuginfo-install is included with later versions of the yum-utils package (for example, version 1.1.10), and also requires an appropriate yum repository from which to download and install -debuginfo/-debuginfo-common packages. After configuring yum with the appropriate repository, you can now install the required -devel, debuginfo, and -debuginfo-common packages for your kernel. To install the corresponding packages for a specific kernel, run the following commands: yum install kernelname-devel-version debuginfo-install kernelname-version Replace kernelname with the appropriate kernel variant name (for example, kernel-PAE), and version with the target kernel's version. For example, to install the required kernel information packages for the kernel-PAE-2.6.18-53.1.13.el5 kernel, run: yum install kernel-PAE-devel-2.6.18-53.1.13.el5 debuginfo-install kernel-PAE-2.6.18-53.1.13.el5 If you do not have yum and yum-utils installed (and you are unable to install them), you will have to manually download and install the required kernel information packages. To generate the URL from which to download the required packages, use the following script: Once you have manually downloaded the required packages to the machine, install the RPMs by running rpm --force -ivh package_names.
Pass 1: parsed user script and 45 library script(s) in 340usr/0sys/358real ms. Pass 2: analyzed script: 1 probe(s), 1 function(s), 0 embed(s), 0 global(s) in 290usr/260sys/568real ms. Pass 3: translated to C into "/tmp/stapiArgLX/stap_e5886fa50499994e6a87aacdc43cd392_399.c" in 490usr/430sys/938real ms. Pass 4: compiled C into "stap_e5886fa50499994e6a87aacdc43cd392_399.ko" in 3310usr/430sys/3714real ms. Pass 5: starting run. read performed Pass 5: run completed in 10usr/40sys/73real ms.
The last three lines of the output (i.e. beginning with Pass 5 indicate that SystemTap was able to successfully create the instrumentation to probe the kernel, run the instrumentation, detect the event being probed (in this case, a virtual file system read), and execute a valid handler (print text then close it with no errors).
Note
For the sake of simplicity, we will be using the following terms throughout this section: instrumentation module the kernel module built from a SystemTap script; i.e. the SystemTap module is built on the host system, and will be loaded on the target kernel of target system. host system the system on which you compile the instrumentation modules (from SystemTap scripts), to be loaded on target systems. target system the system for which you are building the instrumentation module (from SystemTap scripts).
target kernel the kernel of the target system. This is the kernel on which you wish to load/run the instrumentation module.
Procedure 2.1. Configuring a Host System and Target Systems 1. Install the systemtap-runtime RPM on each target system. 2. 3. Determine the kernel running on each target system by running uname -r on each target system. Install SystemTap on the host system. You will be building the instrumentation module for the target systems on the host system. For instructions on how to install SystemTap, refer to Section 2.1.1, Installing SystemTap. Using the target kernel version determined earlier, install the target kernel and related RPMs on the host system by the method described in Section 2.1.2, Installing Required Kernel Information RPMs. If multiple target systems use different target kernels, you will need to repeat this step for each different kernel used on the target systems.
4.
After performing Procedure 2.1, Configuring a Host System and Target Systems, you can now build the instrumentation module (for any target system) on the host system. To build the instrumentation module, run the following command on the host system (be sure to specify the appropriate values):
Here, kernel_version refers to the version of the target kernel (the output of uname -r on the target machine), script refers to the script to be converted into an instrumentation module, and module_name is the desired name of the instrumentation module.
Note
To determine the architecture notation of a running kernel, run uname -m.
Once the the instrumentation module is compiled, copy it to the target system and then load it using:
staprun module_name.ko
For example, to create the instrumentation module simple.ko from a SystemTap script named simple.stp for the target kernel 2.6.18-92.1.10.el5 (on x86_64 architecture), use the following command: stap -r 2.6.18-92.1.10.el5 -e 'probe vfs.read {exit()}' -m simple This will create a module named simple.ko. To use the instrumentation module simple.ko, copy it to the target system and run the following command (on the target system): staprun simple.ko
Important
The host system must be the same architecture and running the same distribution of Linux as the target system in order for the built instrumentation module to work.
(as in stap script -c /bin/cp). For more information about target(), refer to SystemTap Functions. -e 'script' Use script string rather than a file as input for systemtap translator. You can also instruct stap to run scripts from standard input using the switch -. To illustrate:
Example 2.1. Running Scripts From Standard Input Example 2.1, Running Scripts From Standard Input instructs stap to run the script passed by echo to standard input. Any stap options you wish to use should be inserted before the - switch; for instance, to make the example in Example 2.1, Running Scripts From Standard Input more verbose, the command would be: echo "probe timer.s(1) {exit()}" | stap -v For more information about stap, refer to man stap. To run SystemTap instrumentation (i.e. the kernel module built from SystemTap scripts during a cross-instrumentation), use staprun instead. For more information about staprun and crossinstrumentation, refer to Section 2.2, Generating Instrumentation for Other Computers.
Note
The stap options -v and -o also work for staprun. For more information about staprun, refer to man staprun.
Chapter 3.
3.1. Architecture
A SystemTap session begins when you run a SystemTap script. This session occurs in the following fashion: Procedure 3.1. SystemTap Session 1. First, SystemTap checks the script against the existing tapset library (normally in /usr/share/ systemtap/tapset/ for any tapsets used. SystemTap will then substitute any located tapsets with their corresponding definitions in the tapset library. 2. SystemTap then translates the script to C, running the system C compiler to create a kernel module from it. The tools that perform this step are contained in the systemtap package (refer to Section 2.1.1, Installing SystemTap for more information). SystemTap loads the module, then enables all the probes (events and handlers) in the script. The staprun in the systemtap-runtime package (refer to Section 2.1.1, Installing SystemTap for more information) provides this functionality. As the events occur, their corresponding handlers are executed. Once the SystemTap session is terminated, the probes are disabled, and the kernel module is unloaded.
3.
4. 5.
This sequence is driven from a single command-line program: stap. This program is SystemTap's main front-end tool. For more information about stap, refer to man stap (once SystemTap is properly installed on your machine).
Note
An event and its corresponding handler is collectively called a probe. A SystemTap script can have multiple probes. A probe's handler is commonly referred to as a probe body. In terms of application development, using events and handlers is similar to instrumenting the code by inserting diagnostic print statements in a program's sequence of commands. These diagnostic print statements allow you to view a history of commands executed once the program is run. SystemTap scripts allow insertion of the instrumentation code without recompilation of the code and allows more flexibility with regard to handlers. Events serve as the triggers for handlers to run; handlers can be specified to record specified data and print it in a certain manner.
Format
SystemTap scripts use the file extension .stp, and contains probes written in the following format:
SystemTap supports multiple events per probe; multiple events are delimited by a comma (,). If multiple events are specified in a single probe, SystemTap will execute the handler when any of the specified events occur. Each probe has a corresponding statement block. This statement block is enclosed in braces ({ }) and contains the statements to be executed per event. SystemTap executes these statements in sequence; special separators or terminators are generally not necessary between multiple statements.
Note
Statement blocks in SystemTap scripts follow the same syntax and semantics as the C programming language. A statement block can be nested within another statement block. Systemtap allows you to write functions to factor out code to be used by a number of probes. Thus, rather than repeatedly writing the same series of statements in multiple probes, you can just place the instructions in a function, as in:
The statements in function_name are executed when the probe for event executes. The arguments are optional values passed into the function.
Important
Section 3.2, SystemTap Scripts is designed to introduce readers to the basics of SystemTap scripts. To understand SystemTap scripts better, it is advisable that you
10
Event
refer to Chapter 4, Useful SystemTap Scripts; each section therein provides a detailed explanation of the script, its events, handlers, and expected output.
3.2.1. Event
SystemTap events can be broadly classified into two types: synchronous and asynchronous.
Synchronous Events
A synchronous event occurs when any process executes an instruction at a particular location in kernel code. This gives other events a reference point from which more contextual data may be available. Examples of synchronous events include: syscall.system_call The entry to the system call system_call. If the exit from a syscall is desired, appending a .return to the event monitor the exit of the system call instead. For example, to specify the entry and exit of the system call close, use syscall.close and syscall.close.return respectively. vfs.file_operation The entry to the file_operation event for Virtual File System (VFS). Similar to syscall event, appending a .return to the event monitors the exit of the file_operation operation. kernel.function("function") The entry to the kernel function function. For example, kernel.function("sys_open") refers to the "event" that occurs when the kernel function sys_open is called by any thread in the system. To specify the return of the kernel function sys_open, append the return string to the event statement; i.e. kernel.function("sys_open").return. When defining probe events, you can use asterisk (*) for wildcards. You can also trace the entry or exit of a function in a kernel source file. Consider the following example:
Example 3.1. wildcards.stp In the previous example, the first probe's event specifies the entry of ALL functions in the kernel source file net/socket.c. The second probe specifies the exit of all those functions. Note that in this example, there are no statements in the handler; as such, no information will be collected or displayed. kernel.trace("tracepoint") The static probe for tracepoint. Recent kernels (2.6.30 and newer) include instrumentation for specific events in the kernel. These events are statically marked with tracepoints. One example of a tracepoint available in systemtap is kernel.trace("kfree_skb") which indicates each time a network buffer is freed in the kernel. module("module").function("function") Allows you to probe functions within modules. For example:
11
Example 3.2. moduleprobe.stp The first probe in Example 3.2, moduleprobe.stp points to the entry of all functions for the ext3 module. The second probe points to the exits of all functions for that same module; the use of the .return suffix is similar to kernel.function(). Note that the probes in Example 3.2, moduleprobe.stp do not contain statements in the probe handlers, and as such will not print any useful data (as in Example 3.1, wildcards.stp). A system's kernel modules are typically located in /lib/modules/kernel_version, where kernel_version refers to the currently loaded kernel version. Modules use the filename extension .ko.
Asynchronous Events
Asynchronous events are not tied to a particular instruction or location in code. This family of probe points consists mainly of counters, timers, and similar constructs. Examples of asynchronous events include: begin The startup of a SystemTap session; i.e. as soon as the SystemTap script is run. end The end of a SystemTap session. timer events An event that specifies a handler to be executed periodically. For example:
Example 3.3. timer-s.stp Example 3.3, timer-s.stp is an example of a probe that prints hello world every 4 seconds. Note that you can also use the following timer events: timer.ms(milliseconds) timer.us(microseconds) timer.ns(nanoseconds) timer.hz(hertz) timer.jiffies(jiffies) When used in conjunction with other probes that collect information, timer events allows you to print out get periodic updates and see how that information changes over time.
12
Systemtap Handler/Body
Important
SystemTap supports the use of a large collection of probe events. For more information about supported events, refer to man stapprobes. The SEE ALSO section of man stapprobes also contains links to other man pages that discuss supported events for specific subsystems and components.
Example 3.4. helloworld.stp In Example 3.4, helloworld.stp, the event begin (i.e. the start of the session) triggers the handler enclosed in { }, which simply prints hello world followed by a new-line, then exits.
Note
SystemTap scripts continue to run until the exit() function executes. If the users wants to stop the execution of the script, it can interrupted manually with Ctrl+C.
printf ( ) Statements
The printf () statement is one of the simplest functions for printing data. printf () can also be used to display data using a wide variety of SystemTap functions in the following format:
The format string specifies how arguments should be printed. The format string of Example 3.4, helloworld.stp simply instructs SystemTap to print hello world, and contains no format specifiers. You can use the format specifiers %s (for strings) and %d (for numbers) in format strings, depending on your list of arguments. Format strings can have multiple format specifiers, each matching a corresponding argument; multiple arguments are delimited by a comma (,).
Note
Semantically, the SystemTap printf function is very similar to its C language counterpart. The aforementioned syntax and format for SystemTap's printf function is identical to that of the C-style printf. To illustrate this, consider the following probe example:
13
Example 3.5. variables-in-printf-statements.stp Example 3.5, variables-in-printf-statements.stp instructs SystemTap to probe all entries to the system call open; for each event, it prints the current execname() (a string with the executable name) and pid() (the current process ID number), followed by the word open. A snippet of this probe's output would look like:
vmware-guestd(2206) open hald(2360) open hald(2360) open hald(2360) open df(3433) open df(3433) open df(3433) open hald(2360) open
SystemTap Functions
SystemTap supports a wide variety of functions that can be used as printf () arguments. Example 3.5, variables-in-printf-statements.stp uses the SystemTap functions execname() (name of the process that called a kernel function/performed a system call) and pid() (current process ID). The following is a list of commonly-used SystemTap functions: tid() The ID of the current thread. uid() The ID of the current user. cpu() The current CPU number. gettimeofday_s() The number of seconds since UNIX epoch (January 1, 1970). ctime() Convert number of seconds since UNIX epoch to date. pp() A string describing the probe point currently being handled. thread_indent() This particular function is quite useful, providing you with a way to better organize your print results. The function takes one argument, an indentation delta, which indicates how many spaces to add or remove from a thread's "indentation counter". It then returns a string with some generic trace data along with an appropriate number of indentation spaces.
14
Systemtap Handler/Body
The generic data included in the returned string includes a timestamp (number of microseconds since the first call to thread_indent() by the thread), a process name, and the thread ID. This allows you to identify what functions were called, who called them, and the duration of each function call. If call entries and exits immediately precede each other, it is easy to match them. However, in most cases, after a first function call entry is made several other call entries and exits may be made before the first call exits. The indentation counter helps you match an entry with its corresponding exit by indenting the next function call if it is not the exit of the previous one. Consider the following example on the use of thread_indent():
probe kernel.function("*@net/socket.c") { printf ("%s -> %s\n", thread_indent(1), probefunc()) } probe kernel.function("*@net/socket.c").return { printf ("%s <- %s\n", thread_indent(-1), probefunc()) }
Example 3.6. thread_indent.stp Example 3.6, thread_indent.stp prints out the thread_indent() and probe functions at each event in the following format:
0 ftp(7223): -> sys_socketcall 1159 ftp(7223): -> sys_socket 2173 ftp(7223): -> __sock_create 2286 ftp(7223): -> sock_alloc_inode 2737 ftp(7223): <- sock_alloc_inode 3349 ftp(7223): -> sock_alloc 3389 ftp(7223): <- sock_alloc 3417 ftp(7223): <- __sock_create 4117 ftp(7223): -> sock_create 4160 ftp(7223): <- sock_create 4301 ftp(7223): -> sock_map_fd 4644 ftp(7223): -> sock_map_file 4699 ftp(7223): <- sock_map_file 4715 ftp(7223): <- sock_map_fd 4732 ftp(7223): <- sys_socket 4775 ftp(7223): <- sys_socketcall
This sample output contains the following information: The time (in microseconds) since the initial thread_ident() call for the thread (included in the string from thread_ident()). The process name (and its corresponding ID) that made the function call (included in the string from thread_ident()). An arrow signifying whether the call was an entry (<-) or an exit (->); the indentations help you match specific function call entries with their corresponding exits. The name of the function called by the process.
15
name Identifies the name of a specific system call. This variable can only be used in probes that use the event syscall.system_call. target() Used in conjunction with stap script -x process ID or stap script -c command. If you want to specify a script to take an argument of a process ID or command, use target() as the variable in the script to refer to it. For example:
Example 3.7. targetexample.stp When Example 3.7, targetexample.stp is run with the argument -x process ID, it watches all system calls (as specified by the event syscall.*) and prints out the name of all system calls made by the specified process. This has the same effect as specifying if (pid() == process ID) each time you wish to target a specific process. However, using target() makes it easier for you to re-use the script, giving you the ability to simply pass a process ID as an argument each time you wish to run the script (e.g. stap targetexample.stp -x process ID). For more information about supported SystemTap functions, refer to man stapfuncs.
3.3.1. Variables
Variables can be used freely throughout a handler; simply choose a name, assign a value from a function or expression to it, and use it in an expression. SystemTap automatically identifies whether a variable should be typed as a string or integer, based on the type of the values assigned to it. For instance, if you use set the variable foo to gettimeofday_s() (as in foo = gettimeofday_s()), then foo is typed as an number and can be printed in a printf() with the integer format specifier (%d). Note, however, that by default variables are only local to the probe they are used in. This means that variables are initialized, used and disposed at each probe handler invocation. To share a variable between probes, declare the variable name using global outside of the probes. Consider the following example:
global count_jiffies, count_ms probe timer.jiffies(100) { count_jiffies ++ } probe timer.ms(100) { count_ms ++ } probe timer.ms(12345)
16
Conditional Statements
{ hz=(1000*count_jiffies) / count_ms printf ("jiffies:ms ratio %d:%d => CONFIG_HZ=%d\n", count_jiffies, count_ms, hz) exit () }
Example 3.8. timer-jiffies.stp Example 3.8, timer-jiffies.stp computes the CONFIG_HZ setting of the kernel using timers that count jiffies and milliseconds, then computing accordingly. The global statement allows the script to use the variables count_jiffies and count_ms (set in their own respective probes) to be shared with probe timer.ms(12345).
Note
The ++ notation in Example 3.8, timer-jiffies.stp (i.e. count_jiffies ++ and count_ms ++) is used to increment the value of a variable by 1. In the following probe, count_jiffies is incremented by 1 every 100 jiffies:
In this instance, SystemTap understands that count_jiffies is an integer. Because no initial value was assigned to count_jiffies, its initial value is zero by default.
The statement1 is executed if the condition expression is non-zero. The statement2 is executed if the condition expression is zero. The else clause (else statement2)is optional. Both statement1 and statement2 can be statement blocks.
17
else countnonread ++ } probe timer.s(5) { exit() } probe end { printf("VFS reads total %d\n VFS writes total %d\n", countread, countnonread) }
Example 3.9. ifelse.stp Example 3.9, ifelse.stp is a script that counts how many virtual file system reads (vfs_read) and writes (vfs_write) the system performs within a 5-second span. When run, the script increments the value of the variable countread by 1 if the name of the function it probed matches vfs_read (as noted by the condition if (probefunc()=="vfs_read")); otherwise, it increments countnonread (else {countnonread ++}). While Loops Format:
So long as condition is non-zero the block of statements in statement are executed. The statement is often a statement block and it must change a value so condition will eventually be zero. For Loops Format:
The for loop is simply shorthand for a while loop. The following is the equivalent while loop:
Conditional Operators
Aside from == ("is equal to"), you can also use the following operators in your conditional statements: >= Greater than or equal to <= Less than or equal to != Is not equal to
18
Command-Line Arguments
Example 3.10. commandlineargs.stp Example 3.10, commandlineargs.stp is similar to Example 3.1, wildcards.stp, except that it allows you to pass the kernel function to be probed as a command-line argument (as in stap commandlineargs.stp kernel function). You can also specify the script to accept multiple command-line arguments, noting them as @1, @2, and so on, in the order they are entered by the user.
array_name[index_expression]
Here, the array_name is any arbitrary name the array uses. The index_expression is used to refer to a specific unique key in the array. To illustrate, let us try to build an array named foo that specifies the ages of three people (i.e. the unique keys): tom, dick, and harry. To assign them the ages (i.e. associated values) of 23, 24, and 25 respectively, we'd use the following array statements:
Example 3.11. Basic Array Statements You can specify up to 5 index expressons in an array statement, each one delimited by a comma (,). This is useful if you wish to have a key that contains multiple pieces of information. The following line from disktop.stp uses 5 elements for the key: process ID, executable name, user ID, parent process ID, and string "W". It associates the value of devname with that key.
device[pid(),execname(),uid(),ppid(),"W"] = devname
19
Important
All associate arrays must be declared as global, regardless of whether the associate array is used in one or multiple probes.
array_name[index_expression] = value
Example 3.11, Basic Array Statements shows a very basic example of how to set an explicit associated value to a unique key. You can also use a handler function as both your index_expression and value. For example, you can use arrays to set a timestamp as the associated value to a process name (which you wish to use as your unique key), as in:
foo[tid()] = gettimeofday_s()
Example 3.12. Associating Timestamps to Process Names Whenever an event invokes the statement in Example 3.12, Associating Timestamps to Process Names, SystemTap returns the appropriate tid() value (i.e. the ID of a thread, which is then used as the unique key). At the same time, SystemTap also uses the function gettimeofday_s() to set the corresponding timestamp as the associated value to the unique key defined by the function tid(). This creates an array composed of key pairs containing thread IDs and timestamps. In this same example, if tid() returns a value that is already defined in the array foo, the operator will discard the original associated value to it, and replace it with the current timestamp from gettimeofday_s().
Example 3.13. Using Array Values in Simple Computations This example assumes that the array foo was built using the construct in Example 3.12, Associating Timestamps to Process Names (from Section 3.5.1, Assigning an Associated Value). This sets a timestamp that will serve as a reference point, to be used in computing for delta.
20
The construct in Example 3.13, Using Array Values in Simple Computations computes a value for the variable delta by subtracting the associated value of the key tid() from the current gettimeofday_s(). The construct does this by reading the value of tid() from the array. This particular construct is useful for determining the time between two events, such as the start and completion of a read operation.
Note
If the index_expression cannot find the unique key, it returns a value of 0 (for numerical operations, such as Example 3.13, Using Array Values in Simple Computations) or a null/empty string value (for string operations) by default.
array_name[index_expression] ++
Again, you can also use a handler function for your index_expression. For example, if you wanted to tally how many times a specific process performed a read to the virtual file system (using the event vfs.read), you can use the following probe:
Example 3.14. vfsreads.stp In Example 3.14, vfsreads.stp, the first time that the probe returns the process name gnometerminal (i.e. the first time gnome-terminal performs a VFS read), that process name is set as the unique key gnome-terminal with an associated value of 1. The next time that the probe returns the process name gnome-terminal, SystemTap increments the associated value of gnometerminal by 1. SystemTap performs this operation for all process names as the probe returns them.
21
{ reads[execname()] ++ } probe timer.s(3) { foreach (count in reads) printf("%s : %d \n", count, reads[count]) }
Example 3.15. cumulative-vfsreads.stp In the second probe of Example 3.15, cumulative-vfsreads.stp, the foreach statement uses the variable count to reference each iteration of a unique key in the array reads. The reads[count] array statement in the same probe retrieves the associated value of each unique key. Given what we know about the first probe in Example 3.15, cumulative-vfsreads.stp, the script prints VFS-read statistics every 3 seconds, displaying names of processes that performed a VFS-read along with a corresponding VFS-read count. Now, remember that the foreach statement in Example 3.15, cumulative-vfsreads.stp prints all iterations of process names in the array, and in no particular order. You can instruct the script to process the iterations in a particular order by using + (ascending) or - (descending). In addition, you can also limit the number of iterations the script needs to process with the limit value option. For example, consider the following replacement probe:
probe timer.s(3) { foreach (count in reads- limit 10) printf("%s : %d \n", count, reads[count]) }
This foreach statement instructs the script to process the elements in the array reads in descending order (of associated value). The limit 10 option instructs the foreach to only process the first ten iterations (i.e. print the first 10, starting with the highest value).
22
Example 3.16. noncumulative-vfsreads.stp In Example 3.16, noncumulative-vfsreads.stp, the second probe prints the number of VFS reads each process made within the probed 3-second period only. The delete reads statement clears the reads array within the probe.
Note
You can have multiple array operations within the same probe. Using the examples from Section 3.5.4, Processing Multiple Elements in an Array and Section 3.5.5, Clearing/ Deleting Arrays and Array Elements , you can track the number of VFS reads each process makes per 3-second period and tally the cumulative VFS reads of those same processes. Consider the following example:
global reads, totalreads probe vfs.read { reads[execname()] ++ totalreads[execname()] ++ } probe timer.s(3) { printf("=======\n") foreach (count in reads-) printf("%s : %d \n", count, reads[count]) delete reads } probe end { printf("TOTALS\n") foreach (total in totalreads-) printf("%s : %d \n", total, totalreads[total]) }
In this example, the arrays reads and totalreads track the same information, and are printed out in a similar fashion. The only difference here is that reads is cleared every 3second period, whereas totalreads keeps growing.
23
reads[execname()] ++ } probe timer.s(3) { printf("=======\n") foreach (count in reads-) if (reads[count] >= 1024) printf("%s : %dkB \n", count, reads[count]/1024) else printf("%s : %dB \n", count, reads[count]) }
Example 3.17. vfsreads-print-if-1kb.stp Every three seconds, Example 3.17, vfsreads-print-if-1kb.stp prints out a list of all processes, along with how many times each process performed a VFS read. If the associated value of a process name is equal or greater than 1024, the if statement in the script converts and prints it out in kB.
global reads probe vfs.read { reads[execname()] ++ } probe timer.s(3) { printf("=======\n") foreach (count in reads+) printf("%s : %d \n", count, reads[count]) if(["stapio"] in reads) { printf("stapio read detected, exiting\n") exit() } }
Example 3.18. vfsreads-stop-on-stapio2.stp The if(["stapio"] in reads) statement instructs the script to print stapio read detected, exiting once the unique key stapio is added to the array reads.
24
Example 3.19. stat-aggregates.stp In Example 3.19, stat-aggregates.stp, the operator <<< count stores the amount returned by count to to the associated value of the corresponding execname() in the reads array. Remember, these values are stored; they are not added to the associated values of each unique key, nor are they used to replace the current associated values. In a manner of speaking, think of it as having each unique key (execname()) having multiple associated values, accumulating with each probe handler run.
Note
In the context of Example 3.19, stat-aggregates.stp, count returns the amount of data written by the returned execname() to the virtual file system. To extract data collected by statistical aggregates, use the syntax format @extractor(variable/ array index expression). extractor can be any of the following integer extractors: count Returns the number of all values stored into the variable/array index expression. Given the sample probe in Example 3.19, stat-aggregates.stp, the expression @count(writes[execname()]) will return how many values are stored in each unique key in array writes. sum Returns the sum of all values stored into the variable/array index expression. Again, given sample probe in Example 3.19, stat-aggregates.stp, the expression @sum(writes[execname()]) will return the total of all values stored in each unique key in array writes. min Returns the smallest among all the values stored in the variable/array index expression. max Returns the largest among all the values stored in the variable/array index expression. avg Returns the average of all values stored in the variable/array index expression. When using statistical aggregates, you can also build array constructs that use multiple index expressions (to a maximum of 5). This is helpful in capturing additional contextual information during a probe. For example:
25
reads[execname(),pid()] <<< 1 } probe timer.s(3) { foreach([var1,var2] in reads) printf("%s (%d) : %d \n", var1, var2, @count(reads[var1,var2])) }
Example 3.20. Multiple Array Indexes In Example 3.20, Multiple Array Indexes, the first probe tracks how many times each process performs a VFS read. What makes this different from earlier examples is that this array associates a performed read to both a process name and its corresponding process ID. The second probe in Example 3.20, Multiple Array Indexes demonstrates how to process and print the information collected by the array reads. Note how the foreach statement uses the same number of variables (i.e. var1 and var2) contained in the first instance of the array reads from the first probe.
3.6. Tapsets
Tapsets are scripts that form a library of pre-written probes and functions to be used in SystemTap scripts. When a user runs a SystemTap script, SystemTap checks the script's probe events and handlers against the tapset library; SystemTap then loads the corresponding probes and functions before translating the script to C (refer to Section 3.1, Architecture for information on what transpires in a SystemTap session). Like SystemTap scripts, tapsets use the filename extension .stp. The standard library of tapsets is located in /usr/share/systemtap/tapset/ by default. However, unlike SystemTap scripts, tapsets are not meant for direct execution; rather, they constitute the library from which other scripts can pull definitions. Simply put, the tapset library is an abstraction layer designed to make it easier for users to define events and functions. In a manner of speaking, tapsets provide useful aliases for functions that users may want to specify as an event; knowing the proper alias to use is, for the most part, easier than remembering specific kernel functions that might vary between kernel versions. Several handlers and functions in Section 3.2.1, Event and SystemTap Functions are defined in tapsets. For example, thread_indent() is defined in indent.stp.
26
Chapter 4.
4.1. Network
The following sections showcase scripts that trace network-related functions and build a profile of network activity.
nettop.stp
#! /usr/bin/env stap global ifxmit, ifrecv global ifmerged probe netdev.transmit { ifxmit[pid(), dev_name, execname(), uid()] <<< length } probe netdev.receive { ifrecv[pid(), dev_name, execname(), uid()] <<< length } function print_activity() { printf("%5s %5s %-7s %7s %7s %7s %7s %-15s\n", "PID", "UID", "DEV", "XMIT_PK", "RECV_PK", "XMIT_KB", "RECV_KB", "COMMAND") foreach ([pid, dev, exec, uid] in ifrecv) { ifmerged[pid, dev, exec, uid] += @count(ifrecv[pid,dev,exec,uid]); } foreach ([pid, dev, exec, uid] in ifxmit) { ifmerged[pid, dev, exec, uid] += @count(ifxmit[pid,dev,exec,uid]); } foreach ([pid, dev, exec, uid] in ifmerged-) { n_xmit = @count(ifxmit[pid, dev, exec, uid]) n_recv = @count(ifrecv[pid, dev, exec, uid]) printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n", pid, uid, dev, n_xmit, n_recv, n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0, n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0, exec) } print("\n")
27
delete ifxmit delete ifrecv delete ifmerged } probe timer.ms(5000), end, error { print_activity() }
n_xmit ? @sum(ifxmit[pid, dev, exec, uid])/1024 : 0 n_recv ? @sum(ifrecv[pid, dev, exec, uid])/1024 : 0
These expressions are if/else conditionals. The first statement is simply a more concise way of writing the following psuedo code:
nettop.stp tracks which processes are generating network traffic on the system, and provides the following information about each process: PID the ID of the listed process. UID user ID. A user ID of 0 refers to the root user. DEV which ethernet device the process used to send / receive data (e.g. eth0, eth1) XMIT_PK number of packets transmitted by the process RECV_PK number of packets received by the process XMIT_KB amount of data sent by the process, in kilobytes RECV_KB amount of data received by the service, in kilobytes nettop.stp provides network profile sampling every 5 seconds. You can change this setting by editing probe timer.ms(5000) accordingly. Example 4.1, nettop.stp Sample Output contains an excerpt of the output from nettop.stp over a 20-second period:
XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 0 5 0 0 swapper 2 0 0 0 synergyc XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 79 0 5 0 cups-polld 0 61 0 5 firefox 3 32 0 3 swapper
28
2886 11178 PID 0 2886 11178 3611 PID 0 11178 11362 3897 [...]
4 lo 0 eth0 UID 0 4 0 0 UID 0 0 0 0 DEV eth0 lo eth0 eth0 DEV eth0 eth0 eth0 eth0
4 3
4 0
0 0
0 cups-polld 0 synergyc
XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 0 6 0 0 swapper 2 2 0 0 cups-polld 3 0 0 0 synergyc 0 1 0 0 Xorg XMIT_PK RECV_PK XMIT_KB RECV_KB COMMAND 3 42 0 2 swapper 43 1 3 0 synergyc 0 7 0 0 firefox 0 1 0 0 multiload-apple
socket-trace.stp
#! /usr/bin/env stap probe kernel.function("*@net/socket.c").call { printf ("%s -> %s\n", thread_indent(1), probefunc()) } probe kernel.function("*@net/socket.c").return { printf ("%s <- %s\n", thread_indent(-1), probefunc()) }
socket-trace.stp is identical to Example 3.6, thread_indent.stp, which was earlier used in SystemTap Functions to illustrate how thread_indent() works.
[...] 0 Xorg(3611): -> sock_poll 3 Xorg(3611): <- sock_poll 0 Xorg(3611): -> sock_poll 3 Xorg(3611): <- sock_poll 0 gnome-terminal(11106): -> sock_poll 5 gnome-terminal(11106): <- sock_poll 0 scim-bridge(3883): -> sock_poll 3 scim-bridge(3883): <- sock_poll 0 scim-bridge(3883): -> sys_socketcall 4 scim-bridge(3883): -> sys_recv 8 scim-bridge(3883): -> sys_recvfrom 12 scim-bridge(3883):-> sock_from_file 16 scim-bridge(3883):<- sock_from_file 20 scim-bridge(3883):-> sock_recvmsg 24 scim-bridge(3883):<- sock_recvmsg 28 scim-bridge(3883): <- sys_recvfrom 31 scim-bridge(3883): <- sys_recv 35 scim-bridge(3883): <- sys_socketcall
29
[...]
Example 4.2. socket-trace.stp Sample Output Example 4.2, socket-trace.stp Sample Output contains a 3-second excerpt of the output for sockettrace.stp. For more information about the output of this script as provided by thread_indent(), refer to SystemTap Functions Example 3.6, thread_indent.stp.
tcp_connections.stp
#! /usr/bin/env stap probe begin { printf("%6s %16s %6s %6s %16s\n", "UID", "CMD", "PID", "PORT", "IP_SOURCE") } probe kernel.function("tcp_accept").return?, kernel.function("inet_csk_accept").return? { sock = $return if (sock != 0) printf("%6d %16s %6d %6d %16s\n", uid(), execname(), pid(), inet_get_local_port(sock), inet_get_ip_source(sock)) }
While tcp_connections.stp is running, it will print out the following information about any incoming TCP connections accepted by the system in real time: Current UID CMD - the command accepting the connection PID of the command Port used by the connection IP address from which the TCP connection originated
UID 0 0
PORT 22 22
30
dropwatch.stp uses kernel.trace("kfree_skb") to trace packet discards; the script summarizes which locations discard packets every five-second interval.
dropwatch.stp
#! /usr/bin/env stap ############################################################ # Dropwatch.stp # Author: Neil Horman <nhorman@redhat.com> # An example script to mimic the behavior of the dropwatch utility # http://fedorahosted.org/dropwatch ############################################################ # Array to hold the list of drop points we find global locations # Note when we turn the monitor on and off probe begin { printf("Monitoring for dropped packets\n") } probe end { printf("Stopping dropped packet monitor\n") } # increment a drop counter for every location we drop at probe kernel.trace("kfree_skb") { locations[$location] <<< 1 } # Every 5 seconds report our drop locations probe timer.sec(5) { printf("\n") foreach (l in locations-) { printf("%d packets dropped at location %p\n", @count(locations[l]), l) } delete locations }
The kernel.trace("kfree_skb") traces which places in the kernel drop network packets. The kernel.trace("kfree_skb") has two arguments: a pointer to the buffer being freed ($skb) and the location in kernel code the buffer is being freed ($location). Running the dropwatch.stp script 15 seconds would result in output similar in Example 4.4, dropwatch.stp Sample Output. The output lists the number of misses for tracepoint address and the actual address.
Monitoring for dropped packets 51 packets dropped at location 0xffffffff8024cd0f 2 packets dropped at location 0xffffffff8044b472 51 packets dropped at location 0xffffffff8024cd0f 1 packets dropped at location 0xffffffff8044b472 97 packets dropped at location 0xffffffff8024cd0f 1 packets dropped at location 0xffffffff8044b472 Stopping dropped packet monitor
31
To make the location of packet drops more meaningful, refer to the /boot/System.map-`uname r` file. This file lists the starting addresses for each function, allowing you to map the addresses in the output of Example 4.4, dropwatch.stp Sample Output to a specific function name. Given the following snippet of the /boot/System.map-`uname -r` file, the address 0xffffffff8024cd0f maps to the function unix_stream_recvmsg and the address 0xffffffff8044b472 maps to the function arp_rcv:
[...] ffffffff8024c5cd ffffffff8024c5da ffffffff8024c920 ffffffff8024cea1 [...] ffffffff8044addc ffffffff8044b360 ffffffff8044b487 ffffffff8044b48c [...]
T t t t t t t t
4.2. Disk
The following sections showcase scripts that monitor disk and I/O activity.
disktop.stp
#!/usr/bin/env stap # # Copyright (C) 2007 Oracle Corp. # # Get the status of reading/writing disk every 5 seconds, # output top ten entries # # This is free software,GNU General Public License (GPL); # either version 2, or (at your option) any later version. # # Usage: # ./disktop.stp # global io_stat,device global read_bytes,write_bytes probe vfs.read.return { if ($return>0) { if (devname!="N/A") {/*skip read from cache*/ io_stat[pid(),execname(),uid(),ppid(),"R"] += $return device[pid(),execname(),uid(),ppid(),"R"] = devname read_bytes += $return } } }
32
probe vfs.write.return { if ($return>0) { if (devname!="N/A") { /*skip update cache*/ io_stat[pid(),execname(),uid(),ppid(),"W"] += $return device[pid(),execname(),uid(),ppid(),"W"] = devname write_bytes += $return } } } probe timer.ms(5000) { /* skip non-read/write disk */ if (read_bytes+write_bytes) { printf("\n%-25s, %-8s%4dKb/sec, %-7s%6dKb, %-7s%6dKb\n\n", ctime(gettimeofday_s()), "Average:", ((read_bytes+write_bytes)/1024)/5, "Read:",read_bytes/1024, "Write:",write_bytes/1024) /* print header */ printf("%8s %8s %8s %25s %8s %4s %12s\n", "UID","PID","PPID","CMD","DEVICE","T","BYTES") } /* print top ten I/O */ foreach ([process,cmd,userid,parent,action] in io_stat- limit 10) printf("%8d %8d %8d %25s %8s %4s %12d\n", userid,process,parent,cmd, device[process,cmd,userid,parent,action], action,io_stat[process,cmd,userid,parent,action]) /* clear data */ delete io_stat delete device read_bytes = 0 write_bytes = 0 } probe end{ delete io_stat delete device delete read_bytes delete write_bytes }
disktop.stp outputs the top ten processes responsible for the heaviest reads/writes to disk. Example 4.5, disktop.stp Sample Output displays a sample output for this script, and includes the following data per listed process: UID user ID. A user ID of 0 refers to the root user. PID the ID of the listed process. PPID the process ID of the listed process's parent process. CMD the name of the listed process. DEVICE which storage device the listed process is reading from or writing to. T the type of action performed by the listed process; W refers to write, while R refers to read.
33
BYTES the amount of data read to or written from disk. The time and date in the output of disktop.stp is returned by the functions ctime() and gettimeofday_s(). ctime() derives calendar time in terms of seconds passed since the Unix epoch (January 1, 1970). gettimeofday_s() counts the actual number of seconds since Unix epoch, which gives a fairly accurate human-readable timestamp for the output. In this script, the $return is a local variable that stores the actual number of bytes each process reads or writes from the virtual file system. $return can only be used in return probes (e.g. vfs.read.return and vfs.read.return).
[...] Mon Sep 29 03:38:28 2008 , Average: UID 0 0 0 PID 26319 2758 2885 PPID 26294 2757 1
19Kb/sec, Read: 7Kb, Write: 89Kb DEVICE sda5 sda5 sda5 T W R W BYTES 90229 8064 1678
Mon Sep 29 03:38:38 2008 , Average: UID 0 0 PID 2758 2885 PPID 2757 1
1Kb/sec, Read: 7Kb, Write: 1Kb DEVICE sda5 sda5 T R W BYTES 8064 1678
iotime.stp
global global global global start entry_io fd_io time_io
function timestamp:long() { return gettimeofday_us() - start } function proc:string() { return sprintf("%d (%s)", pid(), execname()) } probe begin { start = gettimeofday_us() } global global global global filenames filehandles fileread filewrite
probe syscall.open {
34
filenames[pid()] = user_string($filename) } probe syscall.open.return { if ($return != -1) { filehandles[pid(), $return] = filenames[pid()] fileread[pid(), $return] = 0 filewrite[pid(), $return] = 0 } else { printf("%d %s access %s fail\n", timestamp(), proc(), filenames[pid()]) } delete filenames[pid()] } probe syscall.read { if ($count > 0) { fileread[pid(), $fd] += $count } t = gettimeofday_us(); p = pid() entry_io[p] = t fd_io[p] = $fd } probe syscall.read.return { t = gettimeofday_us(); p = pid() fd = fd_io[p] time_io[p,fd] <<< t - entry_io[p] } probe syscall.write { if ($count > 0) { filewrite[pid(), $fd] += $count } t = gettimeofday_us(); p = pid() entry_io[p] = t fd_io[p] = $fd } probe syscall.write.return { t = gettimeofday_us(); p = pid() fd = fd_io[p] time_io[p,fd] <<< t - entry_io[p] } probe syscall.close { if (filehandles[pid(), $fd] != "") { printf("%d %s access %s read: %d write: %d\n", timestamp(), proc(), filehandles[pid(), $fd], fileread[pid(), $fd], filewrite[pid(), $fd]) if (@count(time_io[pid(), $fd])) printf("%d %s iotime %s time: %d\n", timestamp(), proc(), filehandles[pid(), $fd], @sum(time_io[pid(), $fd])) } delete fileread[pid(), $fd] delete filewrite[pid(), $fd] delete filehandles[pid(), $fd] delete fd_io[pid()] delete entry_io[pid()] delete time_io[pid(),$fd] }
35
iotime.stp tracks each time a system call opens, closes, reads from, and writes to a file. For each file any system call accesses, iotime.stp counts the number of microseconds it takes for any reads or writes to finish and tracks the amount of data (in bytes) read from or written to the file. iotime.stp also uses the local variable $count to track the amount of data (in bytes) that any system call attempts to read or write. Note that $return (as used in disktop.stp from Section 4.2.1, Summarizing Disk Read/Write Traffic) stores the actual amount of data read/written. $count can only be used on probes that track data reads or writes (e.g. syscall.read and syscall.write).
[...] 825946 3364 (NetworkManager) access /sys/class/net/eth0/carrier read: 8190 write: 0 825955 3364 (NetworkManager) iotime /sys/class/net/eth0/carrier time: 9 [...] 117061 2460 (pcscd) access /dev/bus/usb/003/001 read: 43 write: 0 117065 2460 (pcscd) iotime /dev/bus/usb/003/001 time: 7 [...] 3973737 2886 (sendmail) access /proc/loadavg read: 4096 write: 0 3973744 2886 (sendmail) iotime /proc/loadavg time: 11 [...]
Example 4.6. iotime.stp Sample Output Example 4.6, iotime.stp Sample Output prints out the following data: A timestamp, in microseconds Process ID and process name An access or iotime flag The file accessed If a process was able to read or write any data, a pair of access and iotime lines should appear together. The access line's timestamp refer to the time that a given process started accessing a file; at the end of the line, it will show the amount of data read/written (in bytes). The iotime line will show the amount of time (in microseconds) that the process took in order to perform the read or write. If an access line is not followed by an iotime line, it simply means that the process did not read or write any data.
traceio.stp
#! /usr/bin/env stap # traceio.stp # Copyright (C) 2007 Red Hat, Inc., Eugene Teo <eteo@redhat.com> # Copyright (C) 2009 Kai Meyer <kai@unixlords.com> # Fixed a bug that allows this to run longer # And added the humanreadable function # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License version 2 as
36
Track Cumulative IO
# published by the Free Software Foundation. # global reads, writes, total_io probe vfs.read.return { reads[pid(),execname()] += $return total_io[pid(),execname()] += $return } probe vfs.write.return { writes[pid(),execname()] += $return total_io[pid(),execname()] += $return } function humanreadable(bytes) { if (bytes > 1024*1024*1024) { return sprintf("%d GiB", bytes/1024/1024/1024) } else if (bytes > 1024*1024) { return sprintf("%d MiB", bytes/1024/1024) } else if (bytes > 1024) { return sprintf("%d KiB", bytes/1024) } else { return sprintf("%d B", bytes) } } probe timer.s(1) { foreach([p,e] in total_io- limit 10) printf("%8d %15s r: %12s w: %12s\n", p, e, humanreadable(reads[p,e]), humanreadable(writes[p,e])) printf("\n") # Note we don't zero out reads, writes and total_io, # so the values are cumulative since the script started. }
traceio.stp prints the top ten executables generating I/O traffic over time. In addition, it also tracks the cumulative amount of I/O reads and writes done by those ten executables. This information is tracked and printed out in 1-second intervals, and in descending order. Note that traceio.stp also uses the local variable $return, which is also used by disktop.stp from Section 4.2.1, Summarizing Disk Read/Write Traffic.
[...] Xorg floaters multiload-apple sshd pam_timestamp_c staprun snmpd pcscd irqbalance cupsd Xorg floaters multiload-apple sshd r: r: r: r: r: r: r: r: r: r: r: r: r: r: 583401 96 538 71 138 51 46 28 27 4 588140 97 543 72 KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB w: w: w: w: w: w: w: w: w: w: w: w: w: w: 0 7130 537 72 0 51 0 0 4 18 0 7143 542 72 KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB KiB
37
r: r: r: r: r: r:
138 51 46 28 27 4
w: w: w: w: w: w:
0 51 0 0 4 18
traceio2.stp
#! /usr/bin/env stap global device_of_interest probe begin { /* The following is not the most efficient way to do this. One could directly put the result of usrdev2kerndev() into device_of_interest. However, want to test out the other device functions */ dev = usrdev2kerndev($1) device_of_interest = MKDEV(MAJOR(dev), MINOR(dev)) } probe vfs.write, vfs.read { if (dev == device_of_interest) printf ("%s(%d) %s 0x%x\n", execname(), pid(), probefunc(), dev) }
traceio2.stp takes 1 argument: the whole device number. To get this number, use stat -c "0x%D" directory, where directory is located in the device you wish to monitor. The usrdev2kerndev() function converts the whole device number into the format understood by the kernel. The output produced by usrdev2kerndev() is used in conjunction with the MKDEV(), MINOR(), and MAJOR() functions to determine the major and minor numbers of a specific device. The output of traceio2.stp includes the name and ID of any process performing a read/write, the function it is performing (i.e. vfs_read or vfs_write), and the kernel device number. The following example is an excerpt from the full output of stap traceio2.stp 0x805, where 0x805 is the whole device number of /home. /home resides in /dev/sda5, which is the device we wish to monitor.
[...] synergyc(3722) vfs_read 0x800005 synergyc(3722) vfs_read 0x800005 cupsd(2889) vfs_write 0x800005 cupsd(2889) vfs_write 0x800005 cupsd(2889) vfs_write 0x800005
38
[...]
inodewatch-simple.stp
probe vfs.write, vfs.read { dev_nr = $file->f_dentry->d_inode->i_sb->s_dev inode_nr = $file->f_dentry->d_inode->i_ino if (dev_nr == ($1 << 20 | $2) # major/minor device && inode_nr == $3) printf ("%s(%d) %s 0x%x/%u\n", execname(), pid(), probefunc(), dev_nr, inode_nr) }
inodewatch-simple.stp takes the following information about the file as arguments on the command line: The file's major device number. The file's minor device number. The file's inode number. To get this information, use stat -c '%D %i' filename, where filename is an absolute path. For instance: if you wish to monitor /etc/crontab, run stat -c '%D %i' /etc/crontab first. This gives the following output:
805 1078319
805 is the base-16 (hexadecimal) device number. The lower two digits are the minor device number and the upper digits are the major number. 1078319 is the inode number. To start monitoring /etc/ crontab, run stap inodewatch.stp 0x8 0x05 1078319 (The 0x prefixes indicate base-16 values. The output of this command contains the name and ID of any process performing a read/write, the function it is performing (i.e. vfs_read or vfs_write), the device number (in hex format), and the inode number. Example 4.9, inodewatch-simple.stp Sample Output contains the output of stap inodewatch.stp 0x8 0x05 1078319 (when cat /etc/crontab is executed while the script is running) :
39
inodewatch2-simple.stp
global ATTR_MODE = 1 probe kernel.function("inode_setattr") { dev_nr = $inode->i_sb->s_dev inode_nr = $inode->i_ino if (dev_nr == ($1 << 20 | $2) # major/minor device && inode_nr == $3 && $attr->ia_valid & ATTR_MODE) printf ("%s(%d) %s 0x%x/%u %o %d\n", execname(), pid(), probefunc(), dev_nr, inode_nr, $attr->ia_mode, uid()) }
Like inodewatch-simple.stp from Section 4.2.5, Monitoring Reads and Writes to a File, inodewatch2simple.stp takes the targeted file's device number (in integer format) and inode number as arguments. For more information on how to retrieve this information, refer to Section 4.2.5, Monitoring Reads and Writes to a File. The output for inodewatch2-simple.stp is similar to that of inodewatch-simple.stp, except that inodewatch2-simple.stp also contains the attribute changes to the monitored file, as well as the ID of the user responsible (uid()). Example 4.10, inodewatch2-simple.stp Sample Output contains shows the output of inodewatch2-simple.stp while monitoring /home/joe/bigfile when user joe executes chmod 777 /home/joe/bigfile and chmod 666 /home/joe/bigfile.
chmod(17448) inode_setattr 0x800005/6011835 100777 500 chmod(17449) inode_setattr 0x800005/6011835 100666 500
4.3. Profiling
The following sections showcase scripts that profile kernel activity by monitoring function calls.
functioncallcount.stp
#! /usr/bin/env stap # The following line command will probe all the functions # in kernel's memory management code:
40
# # stap
functioncallcount.stp "*@mm/*.c"
probe kernel.function(@1).call { # probe functions listed on commandline called[probefunc()] <<< 1 # add a count efficiently } global called probe end { foreach (fn in called-) # Sort by call count (in decreasing order) # (fn+ in called) # Sort by function name printf("%s %d\n", fn, @count(called[fn])) exit() }
functioncallcount.stp takes the targeted kernel function as an argument. The argument supports wildcards, which enables you to target multiple kernel functions up to a certain extent. You can increase the sample time by editing the timer in the second probe (timer.ms()). The output of functioncallcount.stp contains the name of the function called and how many times it was called during the sample time (in alphabetical order). Example 4.11, functioncallcount.stp Sample Output contains an excerpt from the output of stap countcalls.stp "*@mm/*.c":
[...] __vma_link 97 __vma_link_file 66 __vma_link_list 97 __vma_link_rb 97 __xchg 103 add_page_to_active_list 102 add_page_to_inactive_list 19 add_to_page_cache 19 add_to_page_cache_lru 7 all_vm_events 6 alloc_pages_node 4630 alloc_slabmgmt 67 anon_vma_alloc 62 anon_vma_free 62 anon_vma_lock 66 anon_vma_prepare 98 anon_vma_unlink 97 anon_vma_unlock 66 arch_get_unmapped_area_topdown 94 arch_get_unmapped_exec_area 3 arch_unmap_area_topdown 97 atomic_add 2 atomic_add_negative 97 atomic_dec_and_test 5153 atomic_inc 470 atomic_inc_and_test 1 [...]
41
para-callgraph-simple.stp
function trace(entry_p) { if(tid() in trace) printf("%s%s%s\n",thread_indent(entry_p), (entry_p>0?"->":"<-"), probefunc()) } global trace probe kernel.function(@1).call { if (execname() == "stapio") next # skip our own helper process trace[tid()] = 1 trace(1) } probe kernel.function(@1).return { trace(-1) delete trace[tid()] } probe kernel.function(@2).call { trace(1) } probe kernel.function(@2).return { trace(-1) } function trace(entry_p) { if(tid() in trace) printf("%s%s%s\n",thread_indent(entry_p), (entry_p>0?"->":"<-"), probefunc()) } global trace probe kernel.function(@1).call { if (execname() == "stapio") next # skip our own helper process trace[tid()] = 1 trace(1) } probe kernel.function(@1).return { trace(-1) delete trace[tid()] } probe kernel.function(@2).call { trace(1) } probe kernel.function(@2).return { trace(-1) }
para-callgraph-simple.stp takes two command-line arguments: A trigger function (@1), which enables or disables tracing on a per-thread basis. Tracing in each thread will continue as long as the trigger function has not exited yet. The kernel function/s whose entry/exit call you'd like to trace (@2). para-callgraph-simple.stp uses thread_indent(); as such, its output contains the timestamp, process name, and thread ID of @2 (i.e. the probe function you are tracing). For more information about thread_indent(), refer to its entry in SystemTap Functions. The following example contains an excerpt from the output for stap para-callgraph.stp sys_read '*@fs/*.c':
[...]
42
klogd(1391):->sys_read klogd(1391): ->fget_light klogd(1391): <-fget_light klogd(1391): ->vfs_read klogd(1391): ->rw_verify_area klogd(1391): <-rw_verify_area klogd(1391): ->kmsg_read sendmail(1696):->sys_read sendmail(1696): ->fget_light sendmail(1696): <-fget_light sendmail(1696): ->vfs_read sendmail(1696): ->rw_verify_area sendmail(1696): <-rw_verify_area sendmail(1696): ->proc_file_read sendmail(1696): ->loadavg_read_proc sendmail(1696): ->proc_calc_metrics sendmail(1696): <-proc_calc_metrics sendmail(1696): <-loadavg_read_proc sendmail(1696): <-proc_file_read sendmail(1696): ->dnotify_parent sendmail(1696): <-dnotify_parent sendmail(1696): ->inotify_dentry_parent_queue_event sendmail(1696): <-inotify_dentry_parent_queue_event sendmail(1696): ->inotify_inode_queue_event sendmail(1696): <-inotify_inode_queue_event sendmail(1696): <-vfs_read sendmail(1696):<-sys_read
thread-times.stp
#! /usr/bin/stap probe timer.profile { tid=tid() if (!user_mode()) kticks[tid] <<< 1 else uticks[tid] <<< 1 ticks <<< 1 tids[tid] <<< 1 } global uticks, kticks, ticks global tids probe timer.s(5), end { allticks = @count(ticks) printf ("%5s %7s %7s (of %d ticks)\n", "tid", "%user", "%kernel", allticks) foreach (tid in tids- limit 20) { uscaled = @count(uticks[tid])*10000/allticks kscaled = @count(kticks[tid])*10000/allticks
43
printf ("%5d %3d.%02d%% %3d.%02d%%\n", tid, uscaled/100, uscaled%100, kscaled/100, kscaled%100) } printf("\n") delete delete delete delete } uticks kticks ticks tids
thread-times.stp lists the top 20 processes currently taking up CPU time within a 5-second sample, along with the total number of CPU ticks made during the sample. The output of this script also notes the percentage of CPU time each process used, as well as whether that time was spent in kernel space or user space. Example 4.13, thread-times.stp Sample Output contains a 5-second sample of the output for threadtimes.stp:
tid 0 32169 9815 9859 3611 9861 11106 32167 3897 3800 2886 3243 3862 3782 21767 2522 3883 3775 3943 3873
%user %kernel (of 20002 ticks) 0.00% 87.88% 5.24% 0.03% 3.33% 0.36% 0.95% 0.00% 0.56% 0.12% 0.62% 0.01% 0.37% 0.02% 0.08% 0.08% 0.01% 0.08% 0.03% 0.00% 0.02% 0.00% 0.00% 0.01% 0.01% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00% 0.00%
timeout.stp
#! /usr/bin/env stap # Copyright (C) 2009 Red Hat, Inc. # Written by Ulrich Drepper <drepper@redhat.com> # Modified by William Cohen <wcohen@redhat.com>
44
global process, timeout_count, to global poll_timeout, epoll_timeout, select_timeout, itimer_timeout global nanosleep_timeout, futex_timeout, signal_timeout probe syscall.poll, syscall.epoll_wait { if (timeout) to[pid()]=timeout } probe syscall.poll.return { p = pid() if ($return == 0 && to[p] > 0 ) { poll_timeout[p]++ timeout_count[p]++ process[p] = execname() delete to[p] } } probe syscall.epoll_wait.return { p = pid() if ($return == 0 && to[p] > 0 ) { epoll_timeout[p]++ timeout_count[p]++ process[p] = execname() delete to[p] } } probe syscall.select.return { if ($return == 0) { p = pid() select_timeout[p]++ timeout_count[p]++ process[p] = execname() } } probe syscall.futex.return { if (errno_str($return) == "ETIMEDOUT") { p = pid() futex_timeout[p]++ timeout_count[p]++ process[p] = execname() } } probe syscall.nanosleep.return { if ($return == 0) { p = pid() nanosleep_timeout[p]++ timeout_count[p]++ process[p] = execname() } } probe kernel.function("it_real_fn") { p = pid() itimer_timeout[p]++ timeout_count[p]++ process[p] = execname() } probe syscall.rt_sigtimedwait.return { if (errno_str($return) == "EAGAIN") {
45
p = pid() signal_timeout[p]++ timeout_count[p]++ process[p] = execname() } } probe syscall.exit { p = pid() if (p in process) { delete process[p] delete timeout_count[p] delete poll_timeout[p] delete epoll_timeout[p] delete select_timeout[p] delete itimer_timeout[p] delete futex_timeout[p] delete nanosleep_timeout[p] delete signal_timeout[p] } } probe timer.s(1) { ansi_clear_screen() printf (" pid | poll select epoll itimer futex nanosle foreach (p in timeout_count- limit 20) { printf ("%5d |%7d %7d %7d %7d %7d %7d %7d| %-.38s\n", p, poll_timeout[p], select_timeout[p], epoll_timeout[p], itimer_timeout[p], futex_timeout[p], nanosleep_timeout[p], signal_timeout[p], process[p]) } }
signal| process\n")
timeout.stp tracks how many times each application used the following system calls over time: poll select epoll itimer futex nanosleep signal In some applications, these system calls are used excessively. As such, they are normally identified as "likely culprits" for polling applications. Note, however, that an application may be using a different system call to poll excessively; sometimes, it is useful to find out the top system calls used by the system (refer to Section 4.3.5, Tracking Most Frequently Used System Calls for instructions). Doing so can help you identify any additional suspects, which you can add to timeout.stp for tracking.
select 0
epoll 0
itimer 4727
46
22945 0 4275 4191 22941 4261 3695 3483 4189 1863 2562 4257 4278 4083 3921 4248 3165 29548 1862
| | | | | | | | | | | | | | | | | | |
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 36414 1 0 62 2 0 0 2 0 1 1 60 1728 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0| 0|
scim-bridge swapper mixer_applet2 scim-launcher gnome-terminal escd gdm-binary dhcdbd scim-panel-gtk iscsid pcscd gnome-power-man multiload-apple Xorg gam_server nm-applet xterm httpd iscsid
Example 4.14. timeout.stp Sample Output You can increase the sample time by editing the timer in the second probe (timer.s()). The output of functioncallcount.stp contains the name and UID of the top 20 polling applications, along with how many times each application performed each polling system call (over time). Example 4.14, timeout.stp Sample Output contains an excerpt of the script:
topsys.stp
#! /usr/bin/env stap # # This script continuously lists the top 20 systemcalls in the interval # 5 seconds
47
# global syscalls_count probe syscall.* { syscalls_count[name]++ } function print_systop () { printf ("%25s %10s\n", "SYSCALL", "COUNT") foreach (syscall in syscalls_count- limit 20) { printf("%25s %10d\n", syscall, syscalls_count[syscall]) } delete syscalls_count } probe timer.s(5) { print_systop () printf("--------------------------------------------------------------\n") }
topsys.stp lists the top 20 system calls used by the system per 5-second interval. It also lists how many times each system call was used during that period. Refer to Example 4.15, topsys.stp Sample Output for a sample output.
-------------------------------------------------------------SYSCALL COUNT gettimeofday 1857 read 1821 ioctl 1568 poll 1033 close 638 open 503 select 455 write 391 writev 335 futex 303 recvmsg 251 socket 137 clock_gettime 124 rt_sigprocmask 121 sendto 120 setitimer 106 stat 90 time 81 sigreturn 72 fstat 66 --------------------------------------------------------------
48
most (Section 4.3.4, Monitoring Polling Applications). Monitoring the volume of system calls made by each process provides more data in investigating your system for polling processes and other resource hogs.
syscalls_by_proc.stp
#! /usr/bin/env stap # # # # # # Copyright (C) 2006 IBM Corp. 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 Public License (GPL); either version 2, or (at your option) any later version.
# # Print the system call count by process name in descending order. # global syscalls probe begin { print ("Collecting data... Type Ctrl-C to exit and display results\n") } probe syscall.* { syscalls[execname()]++ } probe end { printf ("%-10s %-s\n", "#SysCalls", "Process Name") foreach (proc in syscalls-) printf("%-10d %-s\n", syscalls[proc], proc) }
syscalls_by_proc.stp lists the top 20 processes performing the highest number of system calls. It also lists how many system calls each process performed during the time period. Refer to Example 4.16, topsys.stp Sample Output for a sample output.
Collecting #SysCalls 1577 692 408 376 299 293 206 95 90 85 84 78 66 [...]
data... Type Ctrl-C to exit and display results Process Name multiload-apple synergyc pcscd mixer_applet2 gnome-terminal Xorg scim-panel-gtk gnome-power-man artsd dhcdbd scim-bridge gnome-screensav scim-launcher
49
If you prefer the output to display the process IDs instead of the process names, use the following script instead.
syscalls_by_pid.stp
#! /usr/bin/env stap # # # # # # Copyright (C) 2006 IBM Corp. 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 Public License (GPL); either version 2, or (at your option) any later version.
# # Print the system call count by process ID in descending order. # global syscalls probe begin { print ("Collecting data... Type Ctrl-C to exit and display results\n") } probe syscall.* { syscalls[pid()]++ } probe end { printf ("%-10s %-s\n", "#SysCalls", "PID") foreach (pid in syscalls-) printf("%-10d %-d\n", syscalls[pid], pid) }
As indicated in the output, you need to manually exit the script in order to display the results. You can add a timed expiration to either script by simply adding a timer.s() probe; for example, to instruct the script to expire after 5 seconds, add the following probe to the script:
50
futexes.stp
#! /usr/bin/env stap # This script tries to identify contended user-space locks by hooking # into the futex system call. global thread_thislock # short global thread_blocktime # global FUTEX_WAIT = 0 /*, FUTEX_WAKE = 1 */ global lock_waits # long-lived stats on (tid,lock) blockage elapsed time global process_names # long-lived pid-to-execname mapping probe syscall.futex { if (op != FUTEX_WAIT) next # don't care about WAKE event originator t = tid () process_names[pid()] = execname() thread_thislock[t] = $uaddr thread_blocktime[t] = gettimeofday_us() } probe syscall.futex.return { t = tid() ts = thread_blocktime[t] if (ts) { elapsed = gettimeofday_us() - ts lock_waits[pid(), thread_thislock[t]] <<< elapsed delete thread_blocktime[t] delete thread_thislock[t] } } probe end { foreach ([pid+, lock] in lock_waits) printf ("%s[%d] lock %p contended %d times, %d avg us\n", process_names[pid], pid, lock, @count(lock_waits[pid,lock]), @avg(lock_waits[pid,lock])) }
futexes.stp needs to be manually stopped; upon exit, it prints the following information: Name and ID of the process responsible for a contention The region of memory it contested How many times the region of memory was contended Average time of contention throughout the probe Example 4.17, futexes.stp Sample Output contains an excerpt from the output of futexes.stp upon exiting the script (after approximately 20 seconds).
[...] automount[2825] lock 0x00bc7784 contended 18 synergyc[3686] lock 0x0861e96c contended 192 synergyc[3758] lock 0x08d98744 contended 192 synergyc[3938] lock 0x0982a8b4 contended 192
us us us us
51
[...]
52
Chapter 5.
It results in the following error message showing that the parser was expecting something other than the probe keyword in column 1 of line 2:
parse error: expected one of '. , ( ? ! { = +=' saw: keyword at perror.stp:2:1 1 parse error(s).
semantic error: type mismatch for identifier 'foo' ... string vs. long
The function foo in the script used the wrong type (i.e. %s or %d). This error will present itself in Example 5.1, error-variable.stp, because the function execname() returns a string the format specifier should be a %s, not %d.
53
while searching for arity N function, semantic error: unresolved function call
A function call or array index expression in the script used an invalid number of arguments/ parameters. In SystemTap arity can either refer to the number of indices for an array, or the number of parameters to a function.
semantic error: probe point mismatch at position N, while resolving probe point foo
SystemTap did not understand what the event or SystemTap function foo refers to. This usually means that SystemTap could not find a match for foo in the tapset library. The N refers to the line and column of the error.
semantic error: no match for probe point, while resolving probe point foo
The events / handler function foo could not be resolved altogether, for a variety of reasons. This error occurs when the script contains the event kernel.function("blah"), and blah does not exist. In some cases, the error could also mean the script contains an invalid kernel file name or source line number.
54
division by 0
The script code performed an invalid division.
aggregation overflow
An array containing aggregate values contains too many distinct key pairs at this time.
MAXNESTING exceeded
Too many levels of function call nesting were attempted. The default nesting of function calls allowed is 10.
MAXACTION exceeded
The probe handler attempted to execute too many statements in the probe handler. The default number of actions allow in a probe handler is 1000.
55
56
Chapter 6.
References
This chapter enumerates other references for more information about SystemTap. It is advisable that you refer to these sources in the course of writing advanced probes and tapsets. SystemTap Wiki The SystemTap Wiki is a collection of links and articles related to the deployment, usage, and development of SystemTap. You can find it in http://sourceware.org/systemtap/wiki/HomePage. SystemTap Tutorial Much of the content in this book comes from the SystemTap Tutorial. The SystemTap Tutorial is a more appropriate reference for users with intermediate to advanced knowledge of C++ and kernel development, and can be found at http://sourceware.org/systemtap/tutorial/. man stapprobes The stapprobes man page enumerates a variety of probe points supported by SystemTap, along with additional aliases defined by the SystemTap tapset library. The bottom of the man page includes a list of other man pages enumerating similar probe points for specific system components, such as stapprobes.scsi, stapprobes.kprocess, stapprobes.signal, etc. man stapfuncs The stapfuncs man page enumerates numerous functions supported by the SystemTap tapset library, along with the prescribed syntax for each one. Note, however, that this is not a complete list of all supported functions; there are more undocumented functions available. SystemTap Language Reference This document is a comprehensive reference of SystemTap's language constructs and syntax. It is recommended for users with a rudimentary to intermediate knowledge of C++ and other similar programming languages. The SystemTap Language Reference is available to all users at http:// sourceware.org/systemtap/langref/ Tapset Developers Guide Once you have sufficient proficiency in writing SystemTap scripts, you can then try your hand out on writing your own tapsets. The Tapset Developers Guide describes how to add functions to your tapset library. Test Suite The systemtap-testsuite package allows you to test the entire SystemTap toolchain without having to build from source. In addition, it also contains numerous examples of SystemTap scripts you can study and test; some of these scripts are also documented in Chapter 4, Useful SystemTap Scripts. By default, the example scripts included in systemtap-testsuite are located in /usr/share/ systemtap/testsuite/systemtap.examples.
57
58
59
60
Index
Symbols
$count sample usage local variables, 36 $return sample usage local variables, 34, 37 @avg (integer extractor) computing for statistical aggregates array operations, 25 @count (integer extractor) computing for statistical aggregates array operations, 25 @max (integer extractor) computing for statistical aggregates array operations, 25 @min (integer extractor) computing for statistical aggregates array operations, 25 @sum (integer extractor) computing for statistical aggregates array operations, 25
A
adding values to statistical aggregates computing for statistical aggregates array operations, 25 advantages of cross-instrumentation, 5 aggregate element not found runtime errors/warnings understainding SystemTap errors, 55 aggregates (statistical) array operations, 24 aggregation overflow runtime errors/warnings understainding SystemTap errors, 55 algebraic formulas using arrays reading values from arrays array operations, 20 architecture notation, determining, 6 architecture of SystemTap, 9 array locals not supported parse/semantics error understanding SystemTap errors, 54 array operations assigning associated values, 20 associating timestamps to process names, 20
associative arrays, 20 clearing arrays/array elements, 22 delete operator, 22 multiple array operations within the same probe, 23 virtual file system reads (non-cumulative), tallying, 22 computing for statistical aggregates, 24 @avg (integer extractor), 25 @count (integer extractor), 25 @max (integer extractor), 25 @min (integer extractor), 25 @sum (integer extractor), 25 adding values to statistical aggregates, 25 count (operator), 25 extracting data collected by statistical aggregates, 25 conditional statements, using arrays in, 23 testing for array membership, 24 deleting arrays and array elements, 22 incrementing associated values, 21 tallying virtual file system reads (VFS reads), 21 multiple elements in an array, 21 processing multiple elements in an array, 21 cumulative virtual file system reads, tallying, 21 foreach, 21 iterations, processing elements in an array as, 21 limiting the output of foreach, 22 ordering the output of foreach, 22 reading values from arrays, 20 computing for timestamp deltas, 20 empty unique keys, 21 using arrays in simple computations, 20 arrays, 19 (see also associative arrays) assigning associated values array operations, 20 associating timestamps to process names, 20 associating timestamps to process names array operations, 20 associated values introduction arrays, 19 associating timestamps to process names assigning associated values array operations, 20 associative arrays
61
Index
introduction, 19 associated values, 19 example, 19 index expression, 19 key pairs, 19 syntax, 19 unique keys, 19 asynchronous events Events, 12
B
begin Events, 12 building instrumentation modules from SystemTap scripts, 5 building kernel modules from SystemTap scripts, 5
C
call graph tracing examples of SystemTap scripts, 41 capabilities of SystemTap Introduction, 1 changes to file attributes, monitoring examples of SystemTap scripts, 40 clearing arrays/array elements array operations, 22 delete operator, 22 multiple array operations within the same probe, 23 virtual file system reads (non-cumulative), tallying, 22 command-line arguments SystemTap handler constructs handlers, 19 compiling instrumentation/kernel modules from SystemTap scripts, 5 components SystemTap scripts introduction, 9 computing for statistical aggregates array operations, 24 @avg (integer extractor), 25 @count (integer extractor), 25 @max (integer extractor), 25 @min (integer extractor), 25 @sum (integer extractor), 25 adding values to statistical aggregates, 25 count (operator), 25 extracting data collected by statistical aggregates, 25
computing for timestamp deltas reading values from arrays array operations, 20 conditional operators conditional statements handlers, 18 conditional statements, using arrays in array operations, 23 testing for array membership, 24 CONFIG_HZ, computing for, 17 contended user-space locks (futex contentions), identifying examples of SystemTap scripts, 50 copy fault runtime errors/warnings understainding SystemTap errors, 55 count operator computing for statistical aggregates array (operator), 25 counting function calls examples of SystemTap scripts, 40 CPU ticks examples of SystemTap scripts, 44 cpu() functions, 14 cross-compiling, 5 cross-instrumentation advantages of, 5 building kernel modules from SystemTap scripts, 5 configuration host system and target system, 6 generating instrumentation from SystemTap scripts, 5 host system, 5 instrumentation module, 5 target kernel, 6 target system, 5 ctime() functions, 14 ctime(), example of usage script examples, 34 cumulative I/O, tracking examples of SystemTap scripts, 36 cumulative virtual file system reads, tallying processing multiple elements in an array array operations, 21
D
delete operator clearing arrays/array elements
62
array operations, 22 determining architecture notation, 6 determining the kernel version, 3 determining time spent in kernel and user space examples of SystemTap scripts, 43 device I/O, monitoring examples of SystemTap scripts, 38 device number of a file (integer format) examples of SystemTap scripts, 39 disk I/O traffic, summarizing script examples, 32 division by 0 runtime errors/warnings understainding SystemTap errors, 55 documentation goals Introduction, 1
E
embedded code in unprivileged script parse/semantics error understanding SystemTap errors, 53 empty unique keys reading values from arrays array operations, 21 end Events, 12 errors parse/semantics error, 53 embedded code in unprivileged script, 53 expected symbol/array index expression, 54 grammatical/typographical script error, 53 guru mode, 53 invalid values to variables/arrays, 53 libdwfl failure, 55 no match for probe point, 54 non-global arrays, 54 probe mismatch, 54 type mismatch for identifier, 53 unresolved function call, 54 unresolved target-symbol expression, 54 unresolved type for identifier, 54 variable modified during 'foreach', 54 runtime errors/warnings, 55 aggregate element not found, 55 aggregation overflow, 55 copy fault, 55 division by 0, 55 MAXACTION exceeded, 55 MAXNESTING exceeded, 55 number of errors: N, skipped probes: M, 55 pointer dereference fault, 55
event types Understanding How SystemTap Works, 9 Events asynchronous events, 12 begin, 12 end, 12 examples of synchronous and asynchronous events, 11 introduction, 11 kernel.function("function"), 11 kernel.trace("tracepoint"), 11 module("module"), 11 synchronous events, 11 syscall.system_call, 11 timer events, 12 vfs.file_operation, 11 wildcards, 11 events and handlers, 9 events wildcards, 11 example introduction arrays, 19 example of multiple command-line arguments examples of SystemTap scripts, 42 examples of synchronous and asynchronous events Events, 11 examples of SystemTap scripts, 27 call graph tracing, 41 CPU ticks, 44 ctime(), example of usage, 34 determining time spent in kernel and user space, 43 file device number (integer format), 39 futex system call, 50 identifying contended user-space locks (i.e. futex contentions), 50 if/else conditionals, alternative syntax, 28 inode number, 39 monitoring changes to file attributes, 40 monitoring device I/O, 38 monitoring I/O time, 34 monitoring incoming TCP connections, 30 monitoring polling applications, 44 monitoring reads and writes to a file, 39 monitoring system calls, 47 monitoring system calls (volume per process), 48 multiple command-line arguments, example of, 42 net/socket.c, tracing functions from, 29
63
Index
network profiling, 27, 30 process deadlocks (arising from futex contentions), 50 stat -c, determining file device number (integer format), 39 stat -c, determining whole device number, 38 summarizing disk I/O traffic, 32 tallying function calls, 40 thread_indent(), sample usage, 42 timer.ms(), sample usage, 41 timer.s(), sample usage, 46, 48 tracing functions called in network socket code, 29 tracking cumulative I/O, 36 trigger function, 42 usrdev2kerndev(), 38 whole device number (usage as a commandline argument), 38 exceeded MAXACTION runtime errors/warnings understainding SystemTap errors, 55 exceeded MAXNESTING runtime errors/warnings understainding SystemTap errors, 55 exit() functions, 13 expected symbol/array index expression parse/semantics error understanding SystemTap errors, 54 extracting data collected by statistical aggregates computing for statistical aggregates array operations, 25
F
feedback contact information for this manual, viii file attributes, monitoring changes to examples of SystemTap scripts, 40 file device number (integer format) examples of SystemTap scripts, 39 file reads/writes, monitoring examples of SystemTap scripts, 39 for loops conditional statements handlers, 18 foreach processing multiple elements in an array array operations, 21 format introduction arrays, 19
format and syntax printf(), 13 SystemTap handler constructs handlers, 16 SystemTap scripts introduction, 10 format specifiers printf(), 13 format strings printf(), 13 function call (unresolved) parse/semantics error understanding SystemTap errors, 54 function calls (incoming/outgoing), tracing examples of SystemTap scripts, 41 function calls, tallying examples of SystemTap scripts, 40 functions, 14 cpu(), 14 ctime(), 14 gettimeofday_s(), 14 pp(), 14 SystemTap scripts introduction, 10 target(), 16 thread_indent(), 14 tid(), 14, 14 uid(), 14 functions (used in handlers) exit(), 13 functions called in network socket code, tracing examples of SystemTap scripts, 29 futex contention, definition examples of SystemTap scripts, 50 futex contentions, identifying examples of SystemTap scripts, 50 futex system call examples of SystemTap scripts, 50
G
gettimeofday_s() functions, 14 global SystemTap handler constructs handlers, 16 goals, documentation Introduction, 1 grammatical/typographical script error parse/semantics error understanding SystemTap errors, 53 guru mode
64
H
handler functions, 14 handlers conditional statements, 17 conditional operators, 18 for loops, 18 if/else, 17 while loops, 18 introduction, 13 SystemTap handler constructs, 16 command-line arguments, 19 global, 16 syntax and format, 16 variable notations, 19 variables, 16 handlers and events, 9 SystemTap scripts introduction, 9 heaviest disk reads/writes, identifying script examples, 32 host system cross-instrumentation, 5 host system and target system cross-instrumentation configuration, 6
I
I/O monitoring (by device) examples of SystemTap scripts, 38 I/O time, monitoring examples of SystemTap scripts, 34 I/O traffic, summarizing script examples, 32 identifier type mismatch parse/semantics error understanding SystemTap errors, 53 identifying contended user-space locks (i.e. futex contentions) examples of SystemTap scripts, 50 identifying heaviest disk reads/writes script examples, 32 if/else conditional statements handlers, 17 if/else conditionals, alternative syntax examples of SystemTap scripts, 28 if/else statements, using arrays in array operations, 23
incoming TCP connections, monitoring examples of SystemTap scripts, 30 incoming/outgoing function calls, tracing examples of SystemTap scripts, 41 incrementing associated values array operations, 21 tallying virtual file system reads (VFS reads), 21 index expression introduction arrays, 19 initial testing, 4 inode number examples of SystemTap scripts, 39 Installation initial testing, 4 kernel information packages, 3 kernel version, determining the, 3 required packages, 3 Setup and Installation, 3 systemtap package, 3 systemtap-runtime package, 3 instrumentation module cross-instrumentation, 5 instrumentation modules from SystemTap scripts, building, 5 integer extractors computing for statistical aggregates array operations, 25 Introduction capabilities of SystemTap, 1 documentation goals, 1 goals, documentation, 1 limitations of SystemTap, 1 performance monitoring, 1 invalid division runtime errors/warnings understainding SystemTap errors, 55 invalid values to variables/arrays parse/semantics error understanding SystemTap errors, 53 iterations, processing elements in an array as processing multiple elements in an array array operations, 21
K
kernel and user space, determining time spent in examples of SystemTap scripts, 43 kernel information packages, 3 kernel modules from SystemTap scripts, building, 5
65
Index
kernel version, determining the, 3 kernel.function("function") Events, 11 kernel.trace("tracepoint") Events, 11 key pairs introduction arrays, 19
L
libdwfl failure parse/semantics error understanding SystemTap errors, 55 limitations of SystemTap Introduction, 1 limiting the output of foreach processing multiple elements in an array array operations, 22 local variables name, 16 sample usage $count, 36 $return, 34, 37
examples of SystemTap scripts, 47 monitoring system calls (volume per process) examples of SystemTap scripts, 48 multiple array operations within the same probe clearing arrays/array elements array operations, 23 multiple command-line arguments, example of examples of SystemTap scripts, 42 multiple elements in an array array operations, 21
N
name local variables, 16 net/socket.c, tracing functions from examples of SystemTap scripts, 29 network profiling examples of SystemTap scripts, 27, 30 network socket code, tracing functions called in examples of SystemTap scripts, 29 network traffic, monitoring examples of SystemTap scripts, 27, 30 no match for probe point parse/semantics error understanding SystemTap errors, 54 non-global arrays parse/semantics error understanding SystemTap errors, 54 number of errors: N, skipped probes: M runtime errors/warnings understainding SystemTap errors, 55
M
MAXACTION exceeded runtime errors/warnings understainding SystemTap errors, 55 MAXNESTING exceeded runtime errors/warnings understainding SystemTap errors, 55 membership (in array), testing for conditional statements, using arrays in array operations, 24 module("module") Events, 11 monitoring changes to file attributes examples of SystemTap scripts, 40 monitoring cumulative I/O examples of SystemTap scripts, 36 monitoring device I/O examples of SystemTap scripts, 38 monitoring I/O time examples of SystemTap scripts, 34 monitoring incoming TCP connections examples of SystemTap scripts, 30 monitoring polling applications examples of SystemTap scripts, 44 monitoring reads and writes to a file examples of SystemTap scripts, 39 monitoring system calls
O
operations assigning associated values associating timestamps to process names, 20 associative arrays, 20 clearing arrays/array elements, 22 delete operator, 22 multiple array operations within the same probe, 23 virtual file system reads (non-cumulative), tallying, 22 computing for statistical aggregates, 24 @avg (integer extractor), 25 @count (integer extractor), 25 @max (integer extractor), 25 @min (integer extractor), 25 @sum (integer extractor), 25 adding values to statistical aggregates, 25
66
count (operator), 25 extracting data collected by statistical aggregates, 25 conditional statements, using arrays in, 23 testing for array membership, 24 deleting arrays and array elements, 22 incrementing associated values, 21 tallying virtual file system reads (VFS reads), 21 multiple elements in an array, 21 processing multiple elements in an array, 21 cumulative virtual file system reads, tallying, 21 foreach, 21 iterations, processing elements in an array as, 21 limiting the output of foreach, 22 ordering the output of foreach, 22 reading values from arrays, 20 computing for timestamp deltas, 20 empty unique keys, 21 using arrays in simple computations, 20 options, stap Usage, 7 ordering the output of foreach processing multiple elements in an array array operations, 22 overflow of aggregation runtime errors/warnings understainding SystemTap errors, 55
P
packages required to run SystemTap, 3 parse/semantics error understanding SystemTap errors, 53 embedded code in unprivileged script, 53 expected symbol/array index expression, 54 grammatical/typographical script error, 53 guru mode, 53 invalid values to variables/arrays, 53 libdwfl failure, 55 no match for probe point, 54 non-global arrays, 54 probe mismatch, 54 type mismatch for identifier, 53 unresolved function call, 54 unresolved target-symbol expression, 54 unresolved type for identifier, 54 variable modified during 'foreach', 54 performance monitoring Introduction, 1
pointer dereference fault runtime errors/warnings understainding SystemTap errors, 55 polling applications, monitoring examples of SystemTap scripts, 44 pp() functions, 14 printf() format specifiers, 13 format strings, 13, 13 syntax and format, 13 printing I/O activity (cumulative) examples of SystemTap scripts, 36 probe mismatch parse/semantics error understanding SystemTap errors, 54 probe point (no match for) parse/semantics error understanding SystemTap errors, 54 probes SystemTap scripts introduction, 10 process deadlocks (arising from futex contentions) examples of SystemTap scripts, 50 processing multiple elements in an array array operations, 21 cumulative virtual file system reads, tallying array operations, 21 foreach array operations, 21 limiting the output of foreach array operations, 22 ordering the output of foreach array operations, 22 profiling the network examples of SystemTap scripts, 27, 30
R
reading values from arrays array operations, 20 empty unique keys, 21 using arrays in simple computations, 20 computing for timestamp deltas array operations, 20 reads/writes to a file, monitoring examples of SystemTap scripts, 39 required packages, 3 RPMs required to run SystemTap, 3 running scripts from standard input, 8 running SystemTap scripts
67
Index
Usage, 7 runtime errors/warnings understainding SystemTap errors, 55 aggregate element not found, 55 aggregation overflow, 55 copy fault, 55 division by 0, 55 MAXACTION exceeded, 55 MAXNESTING exceeded, 55 number of errors: N, skipped probes: M, 55 pointer dereference fault, 55
S
script examples call graph tracing, 41 CPU ticks, 44 ctime(), example of usage, 34 determining time spent in kernel and user space, 43 file device number (integer format), 39 futex system call, 50 identifying contended user-space locks (i.e. futex contentions), 50 if/else conditionals, alternative syntax, 28 inode number, 39 monitoring changes to file attributes, 40 monitoring device I/O, 38 monitoring I/O time, 34 monitoring incoming TCP connections, 30 monitoring polling applications, 44 monitoring reads and writes to a file, 39 monitoring system calls, 47 monitoring system calls (volume per process), 48 multiple command-line arguments, example of, 42 net/socket.c, tracing functions from, 29 network profiling, 27, 30 process deadlocks (arising from futex contentions), 50 stat -c, determining file device number (integer format), 39 stat -c, determining whole device number, 38 summarizing disk I/O traffic, 32 tallying function calls, 40 thread_indent(), sample usage, 42 timer.ms(), sample usage, 41 timer.s(), sample usage, 46, 48 tracing functions called in network socket code, 29 tracking cumulative I/O, 36
trigger function, 42 usrdev2kerndev(), 38 whole device number (usage as a commandline argument), 38 scripts introduction, 9 components, 9 events and handlers, 9 format and syntax, 10 functions, 10 probes, 10 statement blocks, 10 sessions, SystemTap, 9 Setup and Installation, 3 standard input, running scripts from Usage, 8 stap Usage, 7 stap options, 7 stapdev Usage, 7 staprun Usage, 7 stapusr Usage, 7 stat -c, determining file device number (integer format) examples of SystemTap scripts, 39 stat -c, determining whole device number examples of SystemTap scripts, 38 statement blocks SystemTap scripts introduction, 10 statistical aggregates array operations, 24 summarizing disk I/O traffic script examples, 32, 32 synchronous events Events, 11 syntax introduction arrays, 19 syntax and format printf(), 13 SystemTap handler constructs handlers, 16 SystemTap scripts introduction, 10 syscall.system_call Events, 11 system calls volume (per process), monitoring
68
examples of SystemTap scripts, 48 system calls, monitoring examples of SystemTap scripts, 47 SystemTap architecture, 9 SystemTap handlers SystemTap handler constructs, 16 syntax and format, 16 systemtap package, 3 SystemTap script functions, 14 SystemTap scripts introduction, 9 components, 9 events and handlers, 9 format and syntax, 10 functions, 10 probes, 10 statement blocks, 10 useful examples, 27 SystemTap scripts, how to run, 7 SystemTap sessions, 9 SystemTap statements conditional statements, 17 conditional operators, 18 for loops, 18 if/else, 17 while loops, 18 SystemTap handler constructs command-line arguments, 19 global, 16 variable notations, 19 variables, 16 systemtap-runtime package, 3 systemtap-testsuite package sample scripts, 27
T
tallying function calls examples of SystemTap scripts, 40 tallying virtual file system reads (VFS reads) incrementing associated values array operations, 21 Tapsets definition of, 26 target kernel cross-instrumentation, 6 target system cross-instrumentation, 5 target system and host system configuration, 6 target() functions, 16
target-symbol expression, unresolved parse/semantics error understanding SystemTap errors, 54 TCP connections (incoming), monitoring examples of SystemTap scripts, 30 testing for array membership conditional statements, using arrays in array operations, 24 testing, initial, 4 thread_indent() functions, 14 thread_indent(), sample usage examples of SystemTap scripts, 42 tid() functions, 14 time of I/O examples of SystemTap scripts, 34 time spent in kernel/user space, determining examples of SystemTap scripts, 43 timer events Events, 12 timer.ms(), sample usage examples of SystemTap scripts, 41 timer.s(), sample usage examples of SystemTap scripts, 46, 48 timestamp deltas, computing for reading values from arrays array operations, 20 timestamps, association thereof to process names assigning associated values array operations, 20 tracepoint, 11, 30 tracing call graph examples of SystemTap scripts, 41 tracing functions called in network socket code examples of SystemTap scripts, 29 tracing incoming/outgoing function calls examples of SystemTap scripts, 41 tracking cumulative I/O examples of SystemTap scripts, 36 trigger function examples of SystemTap scripts, 42 type mismatch for identifier parse/semantics error understanding SystemTap errors, 53 typographical script error parse/semantics error understanding SystemTap errors, 53
69
Index
U
uid() functions, 14 uname -m, 6 uname -r, 3 understainding SystemTap errors runtime errors/warnings, 55 aggregate element not found, 55 aggregation overflow, 55 copy fault, 55 division by 0, 55 MAXACTION exceeded, 55 MAXNESTING exceeded, 55 number of errors: N, skipped probes: M, 55 pointer dereference fault, 55 Understanding How SystemTap Works, 9 architecture, 9 event types, 9 events and handlers, 9 SystemTap sessions, 9 understanding SystemTap errors parse/semantics error, 53 embedded code in unprivileged script, 53 expected symbol/array index expression, 54 grammatical/typographical script error, 53 guru mode, 53 invalid values to variables/arrays, 53 libdwfl failure, 55 no match for probe point, 54 non-global arrays, 54 probe mismatch, 54 type mismatch for identifier, 53 unresolved function call, 54 unresolved target-symbol expression, 54 unresolved type for identifier, 54 variable modified during 'foreach', 54 unique keys introduction arrays, 19 unprivileged script, embedded code in parse/semantics error understanding SystemTap errors, 53 unresolved function call parse/semantics error understanding SystemTap errors, 54 unresolved target-symbol expression parse/semantics error understanding SystemTap errors, 54 unresolved type for identifier parse/semantics error understanding SystemTap errors, 54
unsafe embedded code in unprivileged script parse/semantics error understanding SystemTap errors, 53 Usage options, stap, 7 running SystemTap scripts, 7 standard input, running scripts from, 8 stap, 7 stapdev, 7 staprun, 7 stapusr, 7 useful examples of SystemTap scripts, 27 user and kernel space, determining time spent in examples of SystemTap scripts, 43 using arrays in simple computations reading values from arrays array operations, 20 Using SystemTap, 3 usrdev2kerndev() examples of SystemTap scripts, 38
V
values, assignment of array operations, 20 variable modified during 'foreach' parse/semantics error understanding SystemTap errors, 54 variable notations SystemTap handler constructs handlers, 19 variables SystemTap handler constructs handlers, 16 variables (local) name, 16 sample usage $count, 36 $return, 34, 37 VFS reads, tallying of incrementing associated values array operations, 21 vfs.file_operation Events, 11 virtual file system reads (cumulative), tallying processing multiple elements in an array array operations, 21 virtual file system reads (non-cumulative), tallying clearing arrays/array elements array operations, 22
70
W
while loops conditional statements handlers, 18 whole device number (usage as a command-line argument) examples of SystemTap scripts, 38 wildcards in events, 11 writes/reads to a file, monitoring examples of SystemTap scripts, 39
71
72