After writing enough analysis scripts for yourself, you may become
known as an expert to your colleagues, who will want to use your
scripts. Systemtap makes it possible to share in a controlled manner;
to build libraries of scripts that build on each other. In fact, all
of the functions (
pid(), etc.) used in the scripts above come
from tapset scripts like that. A ``tapset'' is just a script that
designed for reuse by installation into a special directory.
Systemtap attempts to resolve references to global symbols (probes,
functions, variables) that are not defined within the script by a
systematic search through the tapset library for scripts that define
those symbols. Tapset scripts are installed under the default
/usr/share/systemtap/tapset. A user may give
additional directories with the
-I DIR option. Systemtap
searches these directories for script (
The search process includes subdirectories that are specialized for a particular kernel version and/or architecture, and ones that name only larger kernel families. Naturally, the search is ordered from specific to general, as shown in Figure .
When a script file is found that defines one of the undefined symbols, that entire file is added to the probing session being analyzed. This search is repeated until no more references can become satisfied. Systemtap signals an error if any are still unresolved.
This mechanism enables several programming idioms. First, it allows
some global symbols to be defined only for applicable kernel
version/architecture pairs, and cause an error if their use is
attempted on an inapplicable host. Similarly, the same symbol can be
defined differently depending on kernels, in much the same way that
include/asm/ARCH/ files contain macros that
provide a porting layer.
Another use is to separate the default parameters of a tapset routine from its implementation. For example, consider a tapset that defines code for relating elapsed time intervals to process scheduling activities. The data collection code can be generic with respect to which time unit (jiffies, wall-clock seconds, cycle counts) it can use. It should have a default, but should not require additional run-time checks to let a user choose another. Figure shows a way.
A tapset that exports only data may be as useful as ones that exports functions or probe point aliases (see below). Such global data can be computed and kept up-to-date using probes internal to the tapset. Any outside reference to the global variable would incidentally activate all the required probes.
Probe point aliases allow creation of
new probe points from existing ones. This is useful if the new probe
points are named to provide a higher level of abstraction. For
example, the system-calls tapset defines probe point aliases of the
syscall.open etc., in terms of lower level ones like
kernel.function("sys_open"). Even if some future kernel
sys_open, the aliased name can remain valid.
A probe point alias definition looks like a normal probe. Both start
with the keyword
probe and have a probe handler statement block
at the end. But where a normal probe just lists its probe points, an
alias creates a new name using the assignment (
Another probe that names the new probe point will create an actual
probe, with the handler of the alias prepended.
This prepending behavior serves several purposes. It allows the alias definition to ``preprocess'' the context of the probe before passing control to the user-specified handler. This has several possible uses:
||skip probe unless given condition is met|
||supply probe-describing values|
||extract target variable to plain local variable|
Figure demonstrates a probe point alias definition as well as its use. It demonstrates how a single probe point alias can expand to multiple probe points, even to other aliases. It also includes probe point wildcarding. These functions are designed to compose sensibly.
Sometimes, a tapset needs provide data values from the kernel that
cannot be extracted using ordinary target variables (
This may be because the values are in complicated data structures, may
require lock awareness, or are defined by layers of macros. Systemtap
provides an ``escape hatch'' to go beyond what the language can safely
offer. In certain contexts, you may embed plain raw C in tapsets,
exchanging power for the safety guarantees listed in
section . End-user scripts may not include
embedded C code, unless systemtap is run with the
mode) option. Tapset scripts get guru mode privileges automatically.
Embedded C can be the body of a script function. Instead enclosing
the function body statements in
%}. Any enclosed C code is literally transcribed into the
kernel module: it is up to you to make it safe and correct. In order
to take parameters and return a value, macros
STAP_RETVALUE are made available. The familiar data-gathering
execname(), and their neighbours are
all embedded C functions. Figure contains
Since systemtap cannot examine the C code to infer these types, an
syntax is available to assist the type inference process. Simply
suffix parameter names and/or the function name with
:long to designate the string or numeric type. In addition,
the script may include a
%} block at the outermost
level of the script, in order to transcribe declarative code like
#include <linux/foo.h>. These enable the embedded C functions
to refer to general kernel types.
There are a number of safety-related constraints that should be observed by developers of embedded C code.
trylocktype call to attempt to take the lock. If that fails, give up, do not block.
Using the tapset search mechanism just described, potentially many script files can become selected for inclusion in a single session. This raises the problem of name collisions, where different tapsets accidentally use the same names for functions/globals. This can result in errors at translate or run time.
To control this problem, systemtap tapset developers are advised to follow naming conventions. Here is some of the guidance.
execve?) to update the list incrementally.