diff options
author | ddomingo <ddomingo@redhat.com> | 2008-10-28 14:04:21 +1000 |
---|---|---|
committer | ddomingo <ddomingo@redhat.com> | 2008-10-28 14:04:21 +1000 |
commit | fc03e8e8d406640d6dfa73f9e3890086c9bfb75f (patch) | |
tree | c2e4fb656f94dbc71ddaeb6f28f060e8ec109fad /doc/SystemTap_Beginners_Guide/en-US | |
parent | 709fde54c8c296d537e58af4bc619b18c654f6a2 (diff) | |
download | systemtap-steved-fc03e8e8d406640d6dfa73f9e3890086c9bfb75f.tar.gz systemtap-steved-fc03e8e8d406640d6dfa73f9e3890086c9bfb75f.tar.xz systemtap-steved-fc03e8e8d406640d6dfa73f9e3890086c9bfb75f.zip |
changes as per wcohen, minor additions
Diffstat (limited to 'doc/SystemTap_Beginners_Guide/en-US')
18 files changed, 702 insertions, 434 deletions
diff --git a/doc/SystemTap_Beginners_Guide/en-US/Array-Operations.xml b/doc/SystemTap_Beginners_Guide/en-US/Array-Operations.xml new file mode 100644 index 00000000..ebac139f --- /dev/null +++ b/doc/SystemTap_Beginners_Guide/en-US/Array-Operations.xml @@ -0,0 +1,232 @@ +<?xml version='1.0'?> +<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [ +]> + +<section id="arrayoperators"> + <title>Array Operations in SystemTap</title> + +<para>This section enumerates some of the most commonly used array operations in SystemTap.</para> + +<section id="arrayops-assignvalue"> + <title>Assigning an Associated Value</title> + <para>Use <command>=</command> to set an associated value to indexed unique pairs, as in:</para> + +<screen> +<replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>] = <replaceable>value</replaceable> +</screen> + +<para><xref linkend="arraysimplestexample"/> 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 <command><replaceable>index_expression</replaceable></command> and <command><replaceable>value</replaceable></command>. 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:</para> + +<example id="arrays-timestampprocessname"> + <title>Associating Timestamps to Process Names</title> +<programlisting> +foo[execname()] = gettimeofday_s() +</programlisting> +</example> + +<para>Whenever an event invokes the statement in <xref linkend="arrays-timestampprocessname"/>, SystemTap returns the appropriate <command>execname()</command> value (i.e. the name of a process, which is then used as the unique key). At the same time, SystemTap also uses the function <command>gettimeofday_s()</command> to set the corresponding timestamp as the associated value to the unique key defined by the function <command>execname()</command>. This creates an array composed of key pairs containing process names and timestamps.</para> + +<para>In this same example, if <command>execname()</command> returns a value that is already defined in the array <command>foo</command>, the operator will discard the original associated value to it, and replace it with the current timestamp from <command>gettimeofday_s()</command>.</para> +</section> +<section id="arrayops-readvalues"> + <title>Reading Values From Arrays</title> + <para>You can also use the <command>=</command> operator to read values from an array. This is accomplished by simply including the <command><replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>]</command> as an element in a mathematical expression. For example:</para> + +<example id="arrayreadingvaluesfrom"> + <title>Using Array Values in Simple Computations</title> +<screen> +foo[execname()] = gettimeofday_s() +delta = gettimeofday_s() - foo[execname()] +</screen> +</example> + +<para>In <xref linkend="arrayreadingvaluesfrom"/>, the first statement sets a timestamp associated with the returned value of the handler function <command>execname()</command> as a <emphasis>reference point</emphasis>. The second statement computes a value for the variable <command>delta</command> by subtracting the associated value the reference point from the current <command>gettimeofday_s()</command>.</para> + +<para>In this situation, if the <command><replaceable>index_expression</replaceable></command> cannot find the unique key, it returns a null value (zero) by default. </para> +</section> +<section id="arrayops-increment"> + <title>Incrementing Associated Values</title> + <para>Use <command>++</command> to increment the associated value of a unique key in an array, as in:</para> + +<screen> +<replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>] ++ +</screen> + +<para>Again, you can also use a handler function for your <command><replaceable>index_expression</replaceable></command>. For example, if you wanted to tally how many times a specific process performed a read to the virtual file system (using the event <command>kernel.function("vfs_read")</command>), you can use the following probe:</para> + +<example id="simplesimplevfsread"> + <title>vfsreads.stp</title> +<programlisting> +probe kernel.function("vfs_read") +{ + reads[execname()] ++ +} +</programlisting> +</example> + +<para>In <xref linkend="simplesimplevfsread"/>, the first time that the probe returns the process name <command>gnome-terminal</command> (i.e. the first time <command>gnome-terminal</command> performs a VFS read), that process name is set as the unique key <literal>gnome-terminal</literal> with an associated value of 1. The next time that the probe returns the process name <command>gnome-terminal</command>, SystemTap increments the associated value of <literal>gnome-terminal</literal> by 1. SystemTap performs this operation for <emphasis>all</emphasis> process names as the probe returns them.</para> +</section> + +<section id="arrayops-foreach"> + <title>Processing Elements in a Tuple as Iterations</title> + <para>Once you've collected enough information in an array, you will need to retrieve and process all elements in that array to make it useful. Consider <xref linkend="simplesimplevfsread"/>: the script collects information about how many VFS reads each process performs, but does not specify what to do with it. The obvious means for making <xref linkend="simplesimplevfsread"/> useful is to print the key pairs in the array <command>reads</command>, but how?</para> + + <para>The best way to process all elements in a tuple (treating each element as an iteration) is to use the <command>foreach</command> statement. Consider the following example:</para> + +<example id="simplevfsreadprint"> + <title>cumulative-vfsreads.stp</title> +<programlisting> +global reads +probe kernel.function("vfs_read") +{ + reads[execname()] ++ +} +probe timer.s(3) +{ + foreach (count in reads) + printf("%s : %d \n", count, reads[count]) +} +</programlisting> +</example> + +<para>In the second probe of <xref linkend="simplevfsreadprint"/>, the <command>foreach</command> statement uses the variable <command>count</command> to reference each iteration of a unique key in the array <command>reads</command>. The <command>reads[count]</command> array statement in the same probe retrieves the associated value of each unique key.</para> + +<para>Given what we know about the first probe in <xref linkend="simplevfsreadprint"/>, 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.</para> + +<para>Now, remember that the <command>foreach</command> statement in <xref linkend="simplevfsreadprint"/> prints <emphasis>all</emphasis> 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 <command>+</command> (ascending) or <command>-</command> (descending). In addition, you can also limit the number of iterations the script needs to process with the <command>limit <replaceable>value</replaceable></command> option.</para> + +<para>For example, consider the following replacement probe:</para> +<screen> +probe timer.s(3) +{ + foreach (count in reads+ limit 4) + printf("%s : %d \n", count, reads[count]) +} +</screen> + +<para>This <command>foreach</command> statement instructs the script to process the elements in the array <command>reads</command> in ascending order (of associated value). The <command>limit 4</command> option instructs the script to only process the first four elements in the array (i.e. the first 4, starting with the lowest value).</para> +</section> + +<section id="arrayops-deleting"> + <title>Clearing/Deleting Arrays and Array Elements</title> + + <para>Sometimes, you may need to clear the associated values in array elements, or reset an entire array for re-use in another probe. <xref linkend="simplevfsreadprint"/> in <xref linkend="arrayops-foreach"/> allows you to track how the number of VFS reads per process grows over time, but it does not show you the number of VFS reads each process makes per 3-second period.</para> + + <para>To do that, you will need to clear the values accumulated by the array. You can accomplish this using the <command>delete</command> operator to delete elements in an array, or an entire array. Consider the following example:</para> + +<example id="simplevfsreadprintnotcumulative"> + <title>vfsreads-per-2secs.stp</title> +<programlisting> +global reads
+probe kernel.function("vfs_read")
+{
+ reads[execname()] ++
+}
+probe timer.s(2)
+{
+ printf("=======\n")
+ foreach (count in reads+)
+ printf("%s : %d \n", count, reads[count])
+ delete reads
+}
+</programlisting> +</example> + +<para>In <xref linkend="simplevfsreadprintnotcumulative"/>, the second probe prints the number of VFS reads each process made <emphasis>within the probed 2-second period only</emphasis>. The <command>delete reads</command> statement clears the <command>reads</command> array within the probe.</para> + +<note> + <title>Note</title> + <para>You can have multiple array operations within the same probe. Using the examples from <xref linkend="arrayops-foreach"/> and <xref linkend="arrayops-deleting"/> , you can track the number of VFS reads each process makes per 2-second period <emphasis>and</emphasis> tally the cumulative VFS reads of those same processes. Consider the following example:</para> + +<screen> +global reads, totalreads
+
+probe kernel.function("vfs_read")
+{
+ reads[execname()] ++
+ totalreads[execname()] ++
+}
+
+probe timer.s(2)
+{
+ 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])
+}
+</screen> + +<para>In this example, the arrays <command>reads</command> and <command>totalreads</command> track the same information, and are printed out in a similar fashion. The only difference here is that <command>reads</command> is cleared every 2-second period, whereas <command>totalreads</command> keeps growing.</para> +</note> +</section> +<section id="arrayops-conditionals"> + <title>Using Arrays in Conditional Statements</title> + +<para>You can also use associative arrays in <command>if</command> statements. This is useful if you want to execute a subroutine once a value in the array matches a certain condition. Consider the following example:</para> + +<example id="simplevfsreadprintif"> + <title>vfsreads-stop-on-stapio.stp</title> +<programlisting> +global reads
+probe kernel.function("vfs_read")
+{
+ reads[execname()] ++
+}
+probe timer.s(2)
+{
+ printf("=======\n")
+ foreach (count in reads+)
+ printf("%s : %d \n", count, reads[count])
+ if(reads["stapio"] >= 20)
+ {exit()}
+} +</programlisting> +</example> + +<para>The <command>if(reads["stapio"] >= 20)</command> instructs the script to execute the subroutine <command>exit()</command> once the value associated with the unique key <command>stapio</command> (in the array <command>reads</command>) is greater than or equal to 20.</para> + +<formalpara> + <title>Testing for Membership</title> +<para>You can also test whether a specific unique key is a member of an array. Further, membership in an array can be used in <command>if</command> statements, as in:</para> +</formalpara> + +<screen> +if([<replaceable>index_expression</replaceable>] in <replaceable>array_name</replaceable> +</screen> + +<para>To illustrate this, consider the following example:</para> + +<example id="simplesimplevfsreadprintifmember"> + <title>vfsreads-stop-on-stapio2.stp</title> +<programlisting> +global reads
+
+probe kernel.function("vfs_read")
+{
+ reads[execname()] ++
+}
+
+probe timer.s(2)
+{
+ printf("=======\n")
+ foreach (count in reads+)
+ printf("%s : %d \n", count, reads[count])
+ if(["stapio"] in reads)
+ {printf("stapio read detected, exiting\n")
+ exit()
+ }
+}
+</programlisting> +</example> + +<para>The <command>if(["stapio"] in reads)</command> statement instructs the script to print <computeroutput>stapio read detected, exiting</computeroutput> once the unique key <command>stapio</command> is added to the array <command>reads</command>.</para> +</section> + +</section>
\ No newline at end of file diff --git a/doc/SystemTap_Beginners_Guide/en-US/Arrays.xml b/doc/SystemTap_Beginners_Guide/en-US/Arrays.xml index 0df6c817..6fc99f1d 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Arrays.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Arrays.xml @@ -5,15 +5,15 @@ <section id="associativearrays"> <title>Associative Arrays</title> -<para>SystemTap also supports the use of associative arrays. While an ordinary variable represents a single value, associative arrays can represent a list of values arranged in tabular format. Simply put, an associative array is a collection of unique keys; each key in the array has a value associated with it. Illustrating this visually would be similar to creating a two-column table: the first column would have the unique key, while the second column would have each key's associated value. Each unique key and its associated value is referred to as a <emphasis>key pair</emphasis>.</para> +<para>SystemTap also supports the use of associative arrays. While an ordinary variable represents a single value, associative arrays can represent a list of values. Simply put, an associative array is a collection of unique keys; each key in the array has a value associated with it. Illustrating this visually would be similar to creating a two-column table: the first column would have the unique key, while the second column would have each key's associated value. Each unique key and its associated value is referred to as a <emphasis>key pair</emphasis>.</para> -<para>Since associative arrays are normally processed in multiple probes (as we will demonstrate later), they are declared as <command>global</command> variables in the SystemTap script. The syntax for manipulating arrays is similar to that of <command>awk</command>, and is as follows:</para> +<para>Since associative arrays are normally processed in multiple probes (as we will demonstrate later), they are declared as <command>global</command> variables in the SystemTap script. The syntax for manipulating arrays (i.e. accessing elements in an associative array) is similar to that of <command>awk</command>, and is as follows:</para> <screen> -<replaceable>array_name</replaceable>[<replaceable>index expression</replaceable>] <replaceable>operation</replaceable> +<replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>] <replaceable>operation</replaceable> </screen> -<para>Here, the <command><replaceable>array_name</replaceable></command> is any arbitrary name the array uses. The <command><replaceable>index expression</replaceable></command> is used to refer to a specific unique key (or set of unique keys) in the array, and the <command><replaceable>operation</replaceable></command> defines what to do with the <command><replaceable>index expression</replaceable></command>. To illustrate, let us try to build an array named <command>foo</command> that specifies the ages of three people (i.e. the unique keys): <command>tom</command>, <command>dick</command>, and <command>harry</command>. To assign them the ages (i.e. associated values) of 23, 24, and 25 respectively, we'd use the following array statements:</para> +<para>Here, the <command><replaceable>array_name</replaceable></command> is any arbitrary name the array uses. The <command><replaceable>index_expression</replaceable></command> is used to refer to a specific unique key (or set of unique keys) in the array, and the <command><replaceable>operation</replaceable></command> defines what to do with the <command><replaceable>index_expression</replaceable></command>. To illustrate, let us try to build an array named <command>foo</command> that specifies the ages of three people (i.e. the unique keys): <command>tom</command>, <command>dick</command>, and <command>harry</command>. To assign them the ages (i.e. associated values) of 23, 24, and 25 respectively, we'd use the following array statements:</para> <example id="arraysimplestexample"> @@ -25,9 +25,15 @@ foo["harry"] = 25 </screen> </example> +<important> + <title>Important</title> + <para>Arrays are normally used in multiple probes throughout a script: in most cases, one probe builds the arrays while another probe processes the information collected by the array (e.g. print its elements). Since the treatment of arrays is similar to that of variables, arrays must also be declared globally with the statement <command>global</command> when they are used by multiple probes.</para> +</important> + + <section id="tuples"> <title>Tuples</title> -<para>Another important point to remember in arrays is that each exists in a <emphasis>slot</emphasis> in the array. A key pair's slot is defined by the order in which each pair's unique key is defined. In our sample array <command>foo</command> in <xref linkend="arraysimplestexample"/>, the key pair that uses the unique key <command>tom</command> is in the first slot, since <command>tom</command> was the first unique key to be defined. <command>dick</command> is in the second slot, and so on.</para> +<para>Another important point to remember in arrays is that each element therein (i.e. the indexed expression) exists in a <emphasis>slot</emphasis>. A key pair's slot is defined by the order in which each pair's unique key is defined. In our sample array <command>foo</command> in <xref linkend="arraysimplestexample"/>, the key pair that uses the unique key <command>tom</command> is in the first slot, since <command>tom</command> was the first unique key to be defined. <command>dick</command> is in the second slot, and so on.</para> <para>The sequence in which each key pair appears in an array (as defined by each pair's slot) is referred to as a <emphasis>tuple</emphasis>. Tuples allow us to refer to key pairs in an array by the order in which they appear in the sequence.</para> @@ -46,7 +52,7 @@ foo[2] ++ <note> <title>Note</title> - <para>You can specify up to 5 index index expressons in an array statement, each one delimited by a comma (<command>,</command>). This is useful if you wish to perform the same operation to a set of key pairs. For example, to increase the associated value of all the key pairs defined by <xref linkend="arraysimplestexample"/>, you can use the following statement:</para> + <para>You can specify up to 5 index expressons in an array statement, each one delimited by a comma (<command>,</command>). This is useful if you wish to perform the same operation to a set of key pairs. For example, to increase the associated value of all the key pairs defined by <xref linkend="arraysimplestexample"/>, you can use the following statement:</para> <screen> foo["tom",2,"harry"] ++ @@ -55,63 +61,7 @@ foo["tom",2,"harry"] ++ </section> - -<section id="arrayoperators"> - <title>Commonly Used Array Operators in SystemTap</title> - -<para>This section enumerates some of the most commonly used array operators in SystemTap.</para> - -<variablelist> - -<varlistentry> - <term>Assigning Associated Value</term> - <listitem> - <para>Use <command>=</command> to set an associated value to indexed unique pairs, as in:</para> -<screen> -<replaceable>array_name</replaceable>[<replaceable>index expression</replaceable>] = <replaceable>value</replaceable> -</screen> - -<para><xref linkend="arraysimplestexample"/> 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 <command><replaceable>index expression</replaceable></command> and <command><replaceable>value</replaceable></command>. 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:</para> - -<example id="arrays-timestampprocessname"> - <title>Associating Timestamps to Process Names</title> -<programlisting> -foo[execname()] = gettimeofday_s() -</programlisting> -</example> - -<para>Whenever an event invokes the statement in <xref linkend="arrays-timestampprocessname"/>, SystemTap returns the appropriate <command>execname()</command> value (i.e. the name of a process, which is then used as the unique key). At the same time, SystemTap also uses the function <command>gettimeofday_s()</command> to set the corresponding timestamp as the associated value to the unique key defined by the function <command>execname()</command>. This creates an array composed of key pairs containing process names and timestamps.</para> - -<para>In this same example, if <command>execname()</command> returns a value that is already defined in the array <command>foo</command>, the operator will discard the original associated value to it, and replace it with the current timestamp from <command>gettimeofday_s()</command>.</para> - </listitem> -</varlistentry> - -<varlistentry> - <term>Incrementing Associated Values</term> - <listitem> - <para>Use <command>++</command> to increment the associated value of a unique key in an array, as in:</para> -<screen> -<replaceable>array_name</replaceable>[<replaceable>index expression</replaceable>] ++ -</screen> - -<para>Again, you can also use a handler function for your <command><replaceable>index expression</replaceable></command>. For example, if you wanted to tally how many times a specific process performed a read to the virtual file system (using the event <command>kernel.function("vfs_read")</command>), you can use the following probe:</para> - -<formalpara id="simplesimplevfsread"> - <title>vfsreads.stp</title> -<para> -<programlisting> -probe kernel.function("vfs_read") -{ - reads[execname()] ++ -} -</programlisting> -</para> -</formalpara> - -<para>In <xref linkend="simplesimplevfsread"/>, the first time that the probe returns the process name <command>gnome-terminal</command> (i.e. the first time <command>gnome-terminal</command> performs a VFS read), that process name is set as the unique key <literal>gnome-terminal</literal> with an associated value of 1. The next time that the probe returns the process name <command>gnome-terminal</command>, SystemTap increments the associated value of <command>gnome-terminal</command> by 1. SystemTap performs this operation for <emphasis>all</emphasis> process names as the probe returns them.</para> - - </listitem> -</varlistentry> +<xi:include href="Array-Operations.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <!-- <varlistentry> <term></term> @@ -120,12 +70,7 @@ probe kernel.function("vfs_read") </listitem> </varlistentry> --> - -</variablelist> -<remark>need to add a link to a more complete list of commonly used array operators!</remark> -</section> - - + @@ -139,7 +84,7 @@ probe kernel.function("vfs_read") <para>The simplest form of data manipulation in associative arrays is incrementing the associated value of a unique key in the array. The syntax for this operation is as follows:</para> </formalpara> <screen> -<replaceable>array_name</replaceable>[<replaceable>index expression</replaceable>"] ++ +<replaceable>array_name</replaceable>[<replaceable>index_expression</replaceable>"] ++ </screen> <para>Here, the <command>++</command> operation instructs SystemTap to increment the associated value of <command><replaceable>unique_key</replaceable></command> by <command><replaceable>value</replaceable></command>. For example, to increase the associated value of unique key <command>hello</command> in array <command>foo</command> by 4, use:</para> diff --git a/doc/SystemTap_Beginners_Guide/en-US/ScriptConstructs.xml b/doc/SystemTap_Beginners_Guide/en-US/ScriptConstructs.xml index 42054cb9..b1f40669 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/ScriptConstructs.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/ScriptConstructs.xml @@ -47,9 +47,7 @@ probe timer.jiffies(100) { count_jiffies ++ } <para>In some cases, such as in <xref linkend="timerjiffies"/>, a variable may be declared without any specific value as yet. You need to declare such values as integers using the notation <command>++</command>.</para> </note> --> -</section> -<xi:include href="Arrays.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> - +</section> <section id="handlerconditionalstatements"> <title>Conditional Statements</title> <para> @@ -74,20 +72,21 @@ if (<replaceable>condition</replaceable>) <title>ifelse.stp</title> <programlisting> global countread, countnonread
-probe vfs.read,vfs.write
+probe kernel.function("vfs_read"),kernel.function("vfs_write")
{
if (probefunc()=="vfs_read") {
countread ++ }
else {countnonread ++}
}
-probe timer.s(5) {
- exit()}
-probe end {
- printf("VFS reads total %d\n VFS writes total %d\n", countread, countnonread)}
+probe timer.s(5) { exit() }
+probe end
+{
+ printf("VFS reads total %d\n VFS writes total %d\n", countread, countnonread)
+}
</programlisting> </example> -<para><xref linkend="simpleifelseexample"/> is a script that counts how many virtual file system reads (<command>vfs.read</command>) and writes (<command>vfs.write</command>) the system performs within a 5-second span. When run, the script increments the value of the variable <command>countread</command> by 1 if the name of the function it probed matches <command>vfs_read</command> (as noted by the condition <command>if (probefunc()=="vfs_read")</command>); otherwise, it increments <command>countnonread</command> (<command>else {countnonread ++}</command>).</para> +<para><xref linkend="simpleifelseexample"/> is a script that counts how many virtual file system reads (<command>vfs_read</command>) and writes (<command>vfs_write</command>) the system performs within a 5-second span. When run, the script increments the value of the variable <command>countread</command> by 1 if the name of the function it probed matches <command>vfs_read</command> (as noted by the condition <command>if (probefunc()=="vfs_read")</command>); otherwise, it increments <command>countnonread</command> (<command>else {countnonread ++}</command>).</para> </listitem> </varlistentry> @@ -103,11 +102,11 @@ while (<replaceable>condition</replaceable>) {<replaceable>statement</replaceabl <example id="simplewhileexample"> <title>while.stp</title> <programlisting> -global foo
-probe timer.s(1) {
-foo ++
-while (foo<6) {printf("hello world\n")}
-printf("goodbye world\n")
+global foo +probe timer.s(1) { +foo ++ +while (foo<6) {printf("hello world\n")} +printf("goodbye world\n") </programlisting> </example> @@ -137,10 +136,40 @@ for (<replaceable>argument1</replaceable>; <replaceable>argument2</replaceable>; --> </variablelist> - -<para>These constructs are better illustrated in the different examples available in <xref linkend="useful-systemtap-scripts"/>.</para> +<!-- +<para>These constructs are better illustrated in the different examples available in <xref linkend="useful-systemtap-scripts"/>.</para>--> + +<remark>need simple, simple examples for FOR and WHILE</remark> + +<formalpara> + <title>Conditional Operators</title> +<para>Aside from <command>==</command> ("is equal to"), you can also use the following operators in your conditional statements:</para> +</formalpara> + +<variablelist> + +<varlistentry> + <term>>=</term> + <listitem> + <para>Greater than or equal to</para> + </listitem> +</varlistentry> + +<varlistentry> + <term><=</term> + <listitem> + <para>Less than or equal to</para> + </listitem> +</varlistentry> + +<varlistentry> + <term>!=</term> + <listitem> + <para>Is not equal to</para> + </listitem> +</varlistentry> -<remark>will get back to these ones later</remark> +</variablelist> </section> <section id="commandlineargssect"> <title>Command-Line Arguments</title> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Scripts.xml b/doc/SystemTap_Beginners_Guide/en-US/Scripts.xml index fad12dee..ca360e06 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Scripts.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Scripts.xml @@ -38,9 +38,23 @@ SystemTap scripts use the file extension <filename>.stp</filename>, and are written in the following format: </para> </formalpara> -<programlisting> +<screen> probe <replaceable>event</replaceable>, {<replaceable>handler</replaceable>} -</programlisting> +</screen> + +<para> + Sometimes, you may need to recycle a handler accross multiple probes. Rather than rewrite handler statements accross probes, you can simply recycle them using <firstterm>functions</firstterm>, as in: +</para> + +<screen> +function <replaceable>function_name</replaceable> {<replaceable>handler1</replaceable>} +probe <replaceable>event</replaceable> {<replaceable>function_name</replaceable>} +</screen> + +<para>Here, the probe executes <command><replaceable>handler1</replaceable></command> as the handler for the probed <command><replaceable>event</replaceable></command>.</para> + + + <!-- <para>The <replaceable>exit()</replaceable> condition is optional; this condition safely terminates the session once the script successfully collects the required information the first time.</para> --> @@ -353,13 +367,14 @@ hald(2360) open <para>A string describing the probe point currently being handled.</para> </listitem> </varlistentry> - +<!-- removed, doesnt work as expected anymore <varlistentry> <term>probefunc()</term> <listitem> <para>If known, the name of the function in which the probe was placed.</para> </listitem> </varlistentry> +--> <varlistentry> <term>thread_indent()</term> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Understanding_How_SystemTap_Works.xml b/doc/SystemTap_Beginners_Guide/en-US/Understanding_How_SystemTap_Works.xml index 81926b34..f63a8ca5 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Understanding_How_SystemTap_Works.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Understanding_How_SystemTap_Works.xml @@ -53,6 +53,7 @@ </section> <xi:include href="Scripts.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="ScriptConstructs.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> +<xi:include href="Arrays.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <!-- <section id="understanding-scripts"> <title>SystemTap Scripts</title> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-disktop.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-disktop.xml index cfc76c07..02028603 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-disktop.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-disktop.xml @@ -16,9 +16,54 @@ <para>This section describes how to identify which processes are performing the heaviest disk reads/writes to the system.</para> <formalpara id="scriptdisktop"> - <title>disktop.stp</title> + <title>disktop.stp</title> <para> <programlisting> +<xi:include parse="text" href="extras/io/disktop.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> +</programlisting> +</para> +</formalpara> + +<para><xref linkend="scriptdisktop"/> outputs the top ten processes responsible for the heaviest reads/writes to disk. <xref linkend="disktopoutput"/> displays a sample output for this script, and includes the following data per listed process:</para> + +<itemizedlist> + <listitem><para><computeroutput>UID</computeroutput> — user ID. A user ID of <computeroutput>0</computeroutput> refers to the root user.</para></listitem> + + <listitem><para><computeroutput>PID</computeroutput> — the ID of the listed process.</para></listitem> + + <listitem><para><computeroutput>PPID</computeroutput> — the process ID of the listed process's <emphasis>parent process</emphasis>.</para></listitem> + + <listitem><para><computeroutput>CMD</computeroutput> — the name of the listed process.</para></listitem> + + <listitem><para><computeroutput>DEVICE</computeroutput> — which storage device the listed process is reading from or writing to.</para></listitem> + + <listitem><para><computeroutput>T</computeroutput> — the type of action performed by the listed process; <computeroutput>W</computeroutput> refers to write, while <computeroutput>R</computeroutput> refers to read.</para></listitem> + + <listitem><para><computeroutput>BYTES</computeroutput> — the amount of data read to or written from disk.</para></listitem> +</itemizedlist> + + +<example id="disktopoutput"> + <title><xref linkend="scriptdisktop"/> Sample Output</title> +<screen> +[...] +Mon Sep 29 03:38:28 2008 , Average: 19Kb/sec, Read: 7Kb, Write: 89Kb + +UID PID PPID CMD DEVICE T BYTES +0 26319 26294 firefox sda5 W 90229 +0 2758 2757 pam_timestamp_c sda5 R 8064 +0 2885 1 cupsd sda5 W 1678 + +Mon Sep 29 03:38:38 2008 , Average: 1Kb/sec, Read: 7Kb, Write: 1Kb + +UID PID PPID CMD DEVICE T BYTES +0 2758 2757 pam_timestamp_c sda5 R 8064 +0 2885 1 cupsd sda5 W 1678 +</screen> +</example> + +<!-- +<programlisting> global io_stat,device global read_bytes,write_bytes @@ -76,47 +121,7 @@ probe end{ delete write_bytes } </programlisting> -</para> -</formalpara> - -<para><xref linkend="scriptdisktop"/> outputs the top ten processes responsible for the heaviest reads/writes to disk. <xref linkend="disktopoutput"/> displays a sample output for this script, and includes the following data per listed process:</para> - -<itemizedlist> - <listitem><para><computeroutput>UID</computeroutput> — user ID. A user ID of <computeroutput>0</computeroutput> refers to the root user.</para></listitem> - - <listitem><para><computeroutput>PID</computeroutput> — the ID of the listed process.</para></listitem> - - <listitem><para><computeroutput>PPID</computeroutput> — the process ID of the listed process's <emphasis>parent process</emphasis>.</para></listitem> - - <listitem><para><computeroutput>CMD</computeroutput> — the name of the listed process.</para></listitem> - - <listitem><para><computeroutput>DEVICE</computeroutput> — which storage device the listed process is reading from or writing to.</para></listitem> - - <listitem><para><computeroutput>T</computeroutput> — the type of action performed by the listed process; <computeroutput>W</computeroutput> refers to write, while <computeroutput>R</computeroutput> refers to read.</para></listitem> - - <listitem><para><computeroutput>BYTES</computeroutput> — the amount of data read to or written from disk.</para></listitem> -</itemizedlist> - - -<example id="disktopoutput"> - <title><xref linkend="scriptdisktop"/> Sample Output</title> -<screen> -[...] -Mon Sep 29 03:38:28 2008 , Average: 19Kb/sec, Read: 7Kb, Write: 89Kb - -UID PID PPID CMD DEVICE T BYTES -0 26319 26294 firefox sda5 W 90229 -0 2758 2757 pam_timestamp_c sda5 R 8064 -0 2885 1 cupsd sda5 W 1678 - -Mon Sep 29 03:38:38 2008 , Average: 1Kb/sec, Read: 7Kb, Write: 1Kb - -UID PID PPID CMD DEVICE T BYTES -0 2758 2757 pam_timestamp_c sda5 R 8064 -0 2885 1 cupsd sda5 W 1678 -</screen> -</example> - +--> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-functioncalls.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-functioncalls.xml index 4ebfa6fa..0be71417 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-functioncalls.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-functioncalls.xml @@ -19,19 +19,10 @@ no script in examples <para>This section describes how to identify how many times the system called a specific kernel function in a 30-second sample. Depending on your use of wildcards, you can also use this script to target multiple kernel functions.</para> <formalpara id="countcalls"> - <title>countcalls.stp</title> + <title>functioncallcount.stp</title> <para> <programlisting> -probe kernel.function(@1) { # probe function passed as argument from stdin -called[probefunc()] <<< 1 # add a count efficiently -} -global called -probe end,timer.ms(30000) { - foreach (fn+ in called) # Sort by function name - # (fn in called-) # Sort by call count (in decreasing order) - printf("%s %d\n", fn, @count(called[fn])) - exit() -} +<xi:include parse="text" href="extras/profiling/functioncallcount.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -74,7 +65,16 @@ atomic_inc_and_test 1 [...] </screen> </example> - +<!--probe kernel.function(@1) { # probe function passed as argument from stdin +called[probefunc()] <<< 1 # add a count efficiently +} +global called +probe end,timer.ms(30000) { +foreach (fn+ in called) # Sort by function name +# (fn in called-) # Sort by call count (in decreasing order) +printf("%s %d\n", fn, @count(called[fn])) +exit() +}--> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-futexes.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-futexes.xml index 64a3f1c1..6f61d456 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-futexes.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-futexes.xml @@ -23,10 +23,39 @@ no script in examples <para>To do this, <xref linkend="futexcontention"/> probes the <command>futex</command> system call.</para> <formalpara id="futexcontention"> - <title>futexcontention.stp</title> + <title>futexes.stp</title> <para> <programlisting> -global thread_thislock # short +<xi:include parse="text" href="extras/process/futexes.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> +</programlisting> +</para> +</formalpara> + +<para><xref linkend="futexcontention"/> needs to be manually stopped; upon exit, it prints the following information:</para> + +<itemizedlist> + <listitem><para>Name and ID of the process responsible for a contention</para></listitem> + <listitem><para>The region of memory it contested</para></listitem> + <listitem><para>How many times the region of memory was contended</para></listitem> + <listitem><para>Average time of contention throughout the probe</para></listitem> +</itemizedlist> + +<para><xref linkend="futexcontentionoutput"/> contains an excerpt from the output of <xref linkend="futexcontention"/> upon exiting the script (after approximately 20 seconds).</para> + + +<example id="futexcontentionoutput"> + <title><xref linkend="futexcontention"/> Sample Output</title> +<screen> +[...] +automount[2825] lock 0x00bc7784 contended 18 times, 999931 avg us +synergyc[3686] lock 0x0861e96c contended 192 times, 101991 avg us +synergyc[3758] lock 0x08d98744 contended 192 times, 101990 avg us +synergyc[3938] lock 0x0982a8b4 contended 192 times, 101997 avg us +[...] +</screen> +</example> + +<!-- global thread_thislock # short global thread_blocktime # global FUTEX_WAIT = 0, FUTEX_WAKE = 1 @@ -56,33 +85,6 @@ 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])) -} -</programlisting> -</para> -</formalpara> - -<para><xref linkend="futexcontention"/> needs to be manually stopped; upon exit, it prints the following information:</para> - -<itemizedlist> - <listitem><para>Name and ID of the process responsible for a contention</para></listitem> - <listitem><para>The region of memory it contested</para></listitem> - <listitem><para>How many times the region of memory was contended</para></listitem> - <listitem><para>Average time of contention throughout the probe</para></listitem> -</itemizedlist> - -<para><xref linkend="futexcontentionoutput"/> contains the output of <xref linkend="futexcontention"/> upon exiting the script after approximately 20 seconds.</para> - - -<example id="futexcontentionoutput"> - <title><xref linkend="futexcontention"/> Sample Output</title> -<screen> -automount[2825] lock 0x00bc7784 contended 18 times, 999931 avg us -synergyc[3686] lock 0x0861e96c contended 192 times, 101991 avg us -synergyc[3758] lock 0x08d98744 contended 192 times, 101990 avg us -synergyc[3938] lock 0x0982a8b4 contended 192 times, 101997 avg us -</screen> -</example> - - +} --> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch.xml index 96e58bb4..55465428 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch.xml @@ -19,20 +19,10 @@ no script in examples <para>This section describes how to monitor reads from and writes to a file in real time. </para> <formalpara id="inodewatch"> - <title>inodewatch.stp</title> + <title>inodewatch-simple.stp</title> <para> <programlisting> -probe kernel.function ("vfs_write"), - kernel.function ("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) -} +<xi:include parse="text" href="extras/general/inodewatch-simple.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -66,6 +56,20 @@ cat(16437) vfs_read 0x800005/1078319 </screen> </example> +<!-- + probe kernel.function ("vfs_write"), + kernel.function ("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) +} + + --> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch2.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch2.xml index 28dbcf75..d13f3a79 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch2.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-inodewatch2.xml @@ -19,21 +19,10 @@ no script in examples <para>This section describes how to monitor if any processes are changing the attributes of a targeted file, in real time. </para> <formalpara id="inodewatch2"> - <title>inodewatch2.stp</title> + <title>inodewatch2-simple.stp</title> <para> <programlisting> -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()) - } +<xi:include parse="text" href="extras/general/inodewatch2-simple.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -51,7 +40,22 @@ chmod(17448) inode_setattr 0x800005/6011835 100777 500 chmod(17449) inode_setattr 0x800005/6011835 100666 500 </screen> </example> +<!-- +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()) + } + + + --> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-iotop.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-iotop.xml index 42b9e025..9c56c971 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-iotop.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-iotop.xml @@ -11,31 +11,7 @@ <title>iotop.stp</title> <para> <programlisting> -global reads, writes, total_io - -probe kernel.function("vfs_read") { - reads[execname()] += $count -} - -probe kernel.function("vfs_write") { - writes[execname()] += $count -} - -# print top 10 IO processes every 5 seconds -probe timer.s(5) { - foreach (name in writes) - total_io[name] += writes[name] - foreach (name in reads) - total_io[name] += reads[name] - printf ("%16s\t%10s\t%10s\n", "Process", "KB Read", "KB Written") - foreach (name in total_io- limit 10) - printf("%16s\t%10d\t%10d\n", name, - reads[name]/1024, writes[name]/1024) - delete reads - delete writes - delete total_io - print("\n") -} +<xi:include parse="text" href="extras/io/iotop.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -73,4 +49,32 @@ probe timer.s(5) { </example> <para><xref linkend="iotopoutput"/> displays top I/O writes and reads within a random 10-second interval. Note that <xref linkend="iotop"/> also detects I/O resulting from SystemTap activity — <xref linkend="iotopoutput"/> also displays reads done by <command>staprun</command>.</para> +<!-- +global reads, writes, total_io + +probe kernel.function("vfs_read") { +reads[execname()] += $count +} + +probe kernel.function("vfs_write") { +writes[execname()] += $count +} + +# print top 10 IO processes every 5 seconds +probe timer.s(5) { +foreach (name in writes) +total_io[name] += writes[name] +foreach (name in reads) +total_io[name] += reads[name] +printf ("%16s\t%10s\t%10s\n", "Process", "KB Read", "KB Written") +foreach (name in total_io- limit 10) +printf("%16s\t%10d\t%10d\n", name, +reads[name]/1024, writes[name]/1024) +delete reads +delete writes +delete total_io +print("\n") +} +--> + </section>
\ No newline at end of file diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-nettop.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-nettop.xml index 331f49a6..40b5ac08 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-nettop.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-nettop.xml @@ -22,59 +22,7 @@ <title>nettop.stp</title> <para> <programlisting> -global ifxmit, ifrecv, ifdevs, ifpid, execname, user - -probe netdev.transmit -{ - p = pid() - execname[p] = execname() - user[p] = uid() - ifdevs[p, dev_name] = dev_name - ifxmit[p, dev_name] <<< length - ifpid[p, dev_name] ++ -} - -probe netdev.receive -{ - p = pid() - execname[p] = execname() - user[p] = uid() - ifdevs[p, dev_name] = dev_name - ifrecv[p, dev_name] <<< length - ifpid[p, dev_name] ++ -} - - -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] in ifpid-) { - n_xmit = @count(ifxmit[pid, dev]) - n_recv = @count(ifrecv[pid, dev]) - printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n", - pid, user[pid], dev, n_xmit, n_recv, - n_xmit ? @sum(ifxmit[pid, dev])/1024 : 0, - n_recv ? @sum(ifrecv[pid, dev])/1024 : 0, - execname[pid]) - } - - print("\n") - - delete execname - delete user - delete ifdevs - delete ifxmit - delete ifrecv - delete ifpid -} - -probe timer.ms(5000) -{ - print_activity() -} +<xi:include parse="text" href="extras/network/nettop.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -126,6 +74,61 @@ probe timer.ms(5000) </screen> </example> - +<!-- + global ifxmit, ifrecv, ifdevs, ifpid, execname, user + + probe netdev.transmit + { + p = pid() + execname[p] = execname() + user[p] = uid() + ifdevs[p, dev_name] = dev_name + ifxmit[p, dev_name] <<< length + ifpid[p, dev_name] ++ + } + + probe netdev.receive + { + p = pid() + execname[p] = execname() + user[p] = uid() + ifdevs[p, dev_name] = dev_name + ifrecv[p, dev_name] <<< length + ifpid[p, dev_name] ++ + } + + + 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] in ifpid-) { + n_xmit = @count(ifxmit[pid, dev]) + n_recv = @count(ifrecv[pid, dev]) + printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n", + pid, user[pid], dev, n_xmit, n_recv, + n_xmit ? @sum(ifxmit[pid, dev])/1024 : 0, + n_recv ? @sum(ifrecv[pid, dev])/1024 : 0, + execname[pid]) + } + + print("\n") + + delete execname + delete user + delete ifdevs + delete ifxmit + delete ifrecv + delete ifpid + } + + probe timer.ms(5000) + { + print_activity() + } + + --> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-paracallgraph.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-paracallgraph.xml index 8547a235..9d726177 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-paracallgraph.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-paracallgraph.xml @@ -19,29 +19,10 @@ <para>This section describes how to trace incoming and outgoing function calls. </para> <formalpara id="scriptcallgraph"> - <title>para-callgraph.stp</title> + <title>para-callgraph-simple.stp</title> <para> <programlisting> -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) } +<xi:include parse="text" href="extras/general/para-callgraph-simple.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -94,6 +75,29 @@ probe kernel.function(@2).return { trace(-1) } </screen> </example> +<!-- + 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) } + + + --> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-sockettrace.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-sockettrace.xml index 43173516..a0afd2c7 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-sockettrace.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-sockettrace.xml @@ -15,15 +15,10 @@ <para>This section describes how to trace functions called from the kernel's <filename>net/socket.c</filename> file. This task helps you identify, in finer detail, how each process interacts with the network at the kernel level.</para> <formalpara id="sockettrace"> - <title>sockettrace.stp</title> + <title>socket-trace.stp</title> <para> <programlisting> -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())
-}
+<xi:include parse="text" href="extras/network/socket-trace.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -34,24 +29,24 @@ probe kernel.function("*@net/socket.c").return { <title><xref linkend="sockettrace"/> Sample Output</title> <screen> [...] -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
+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 [...] </screen> </example> @@ -67,5 +62,16 @@ probe kernel.function("*@net/socket.c").return { <listitem><para>The name of the function called by the process.</para></listitem> </itemizedlist> - </section> +<!-- + 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()) +} + + + --> + +</section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-threadtimes.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-threadtimes.xml index ccf8f8d0..16e843f6 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-threadtimes.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-threadtimes.xml @@ -15,92 +15,96 @@ <para>This section illustrates how to determine the amount of time any given thread is spending in either kernel or user-space.</para> <formalpara id="threadtimes"> - <title>threadtimes.stp</title> + <title>thread-times.stp</title> <para> <programlisting> -function pc:long () %{ /* pure */
- if (CONTEXT->regs)
- THIS->__retvalue = (uint64_t) REG_IP (CONTEXT->regs);
-%}
-
-function kta:long (pc:long) %{ /* pure */ /* is given PC a kernel text address? */
-#if defined (__ia64__)
- THIS->__retvalue = ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)KERNEL_START);
-#else
- THIS->__retvalue = ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)PAGE_OFFSET);
-#endif
-%}
-
-probe timer.profile {
- tid=tid()
- kernel_p = kta(pc())
- if (kernel_p)
- kticks[tid] <<< 1
- else
- uticks[tid] <<< 1
- ticks <<< 1
-}
-
-global uticks, kticks, ticks
-
-global tids
-
-probe timer.s(10), end {
- # gather all seen tids into a single array
- foreach (tid in kticks) tids[tid] += @count(kticks[tid])
- foreach (tid in uticks) tids[tid] += @count(uticks[tid])
-
- 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
- printf ("%5d %3d.%02d%% %3d.%02d%%\n",
- tid, uscaled/100, uscaled%100, kscaled/100, kscaled%100)
- }
- printf("\n")
-
- delete uticks
- delete kticks
- delete ticks
- delete tids
-}
+<xi:include parse="text" href="extras/profiling/thread-times.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> <para><xref linkend="threadtimes"/> 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. </para> - -<para>To run <xref linkend="threadtimes"/>, you need to use the <command>-g</command> option (i.e. <command>stap -g threadtimes.stp</command>). This is because the script contains embedded C.</para> +<!-- +<para>To run <xref linkend="threadtimes"/>, you need to use the <command>-g</command> option (i.e. <command>stap -g threadtimes.stp</command>). This is because the script contains embedded C.</para>--> <para><xref linkend="threadtimesoutput"/> contains a 5-second sample of the output for <xref linkend="threadtimes"/>:</para> <example id="threadtimesoutput"> <title><xref linkend="threadtimes"/> Sample Output</title> <screen> - tid %user %kernel (of 20002 ticks)
- 0 0.00% 87.88%
-32169 5.24% 0.03%
- 9815 3.33% 0.36%
- 9859 0.95% 0.00%
- 3611 0.56% 0.12%
- 9861 0.62% 0.01%
-11106 0.37% 0.02%
-32167 0.08% 0.08%
- 3897 0.01% 0.08%
- 3800 0.03% 0.00%
- 2886 0.02% 0.00%
- 3243 0.00% 0.01%
- 3862 0.01% 0.00%
- 3782 0.00% 0.00%
-21767 0.00% 0.00%
- 2522 0.00% 0.00%
- 3883 0.00% 0.00%
- 3775 0.00% 0.00%
- 3943 0.00% 0.00%
- 3873 0.00% 0.00%
+ tid %user %kernel (of 20002 ticks) + 0 0.00% 87.88% +32169 5.24% 0.03% + 9815 3.33% 0.36% + 9859 0.95% 0.00% + 3611 0.56% 0.12% + 9861 0.62% 0.01% +11106 0.37% 0.02% +32167 0.08% 0.08% + 3897 0.01% 0.08% + 3800 0.03% 0.00% + 2886 0.02% 0.00% + 3243 0.00% 0.01% + 3862 0.01% 0.00% + 3782 0.00% 0.00% +21767 0.00% 0.00% + 2522 0.00% 0.00% + 3883 0.00% 0.00% + 3775 0.00% 0.00% + 3943 0.00% 0.00% + 3873 0.00% 0.00% </screen> </example> +<!-- + function pc:long () %{ /* pure */ + if (CONTEXT->regs) +THIS->__retvalue = (uint64_t) REG_IP (CONTEXT->regs); +%} + +function kta:long (pc:long) %{ /* pure */ /* is given PC a kernel text address? */ +#if defined (__ia64__) +THIS->__retvalue = ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)KERNEL_START); +#else +THIS->__retvalue = ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)PAGE_OFFSET); +#endif +%} + +probe timer.profile { +tid=tid() +kernel_p = kta(pc()) +if (kernel_p) +kticks[tid] <<< 1 +else +uticks[tid] <<< 1 +ticks <<< 1 +} + +global uticks, kticks, ticks + +global tids + +probe timer.s(10), end { +# gather all seen tids into a single array +foreach (tid in kticks) tids[tid] += @count(kticks[tid]) +foreach (tid in uticks) tids[tid] += @count(uticks[tid]) + +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 +printf ("%5d %3d.%02d%% %3d.%02d%%\n", +tid, uscaled/100, uscaled%100, kscaled/100, kscaled%100) +} +printf("\n") + +delete uticks +delete kticks +delete ticks +delete tids +} + + --> </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio.xml index 51f57f6f..892d95ef 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio.xml @@ -12,29 +12,7 @@ <title>traceio.stp</title> <para> <programlisting> -global reads, writes, total_io - -probe kernel.function("vfs_read").return { - reads[execname()] += $return -} - -probe kernel.function("vfs_write").return { - writes[execname()] += $return -} - -probe timer.s(1) { - foreach (p in reads) - total_io[p] += reads[p] - foreach (p in writes) - total_io[p] += writes[p] - foreach(p in total_io- limit 10) - printf("%15s r: %8d KiB w: %8d KiB\n", - p, reads[p]/1024, - writes[p]/1024) - printf("\n") - # Note we don't zero out reads, writes and total_io, - # so the values are cumulative since the script started. -} +<xi:include parse="text" href="extras/io/traceio.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> @@ -68,6 +46,31 @@ pam_timestamp_c r: 138 KiB w: 0 KiB cupsd r: 4 KiB w: 18 KiB </screen> </example> - </section> +<!-- +global reads, writes, total_io + +probe kernel.function("vfs_read").return { +reads[execname()] += $return +} + +probe kernel.function("vfs_write").return { +writes[execname()] += $return +} + +probe timer.s(1) { +foreach (p in reads) +total_io[p] += reads[p] +foreach (p in writes) +total_io[p] += writes[p] +foreach(p in total_io- limit 10) +printf("%15s r: %8d KiB w: %8d KiB\n", +p, reads[p]/1024, +writes[p]/1024) +printf("\n") +# Note we don't zero out reads, writes and total_io, +# so the values are cumulative since the script started. +}--> + +</section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio2.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio2.xml index 342f163b..263d9b69 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio2.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_Scripts-traceio2.xml @@ -22,21 +22,16 @@ </para> <formalpara id="traceio2"> - <title>traceio2.stp</title> + <title>traceio2-simple.stp</title> <para> <programlisting> -probe kernel.function ("vfs_write"), - kernel.function ("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)) - printf ("%s(%d) %s 0x%x\n", execname(), pid(), probefunc(), dev_nr) -} +<xi:include parse="text" href="extras/io/traceio2-simple.stp" xmlns:xi="http://www.w3.org/2001/XInclude" /> </programlisting> </para> </formalpara> +<remark>in new SystemTap, returned a warning, but ran ok.</remark> + <para condition="fedora">For some kernel versions (e.g. <filename>2.6.21-1.3194.fc7</filename>), you may need to revise <xref linkend="traceio2"/> accordingly. SystemTap will output the following error if you need to do so:</para> <screen condition="fedora"> @@ -74,7 +69,18 @@ cupsd(2889) vfs_write 0x800005 cupsd(2889) vfs_write 0x800005 [...] </screen> -</example> +</example> +<!-- +probe kernel.function ("vfs_write"), +kernel.function ("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)) +printf ("%s(%d) %s 0x%x\n", execname(), pid(), probefunc(), dev_nr) +}--> + + </section> diff --git a/doc/SystemTap_Beginners_Guide/en-US/Useful_SystemTap_Scripts.xml b/doc/SystemTap_Beginners_Guide/en-US/Useful_SystemTap_Scripts.xml index 49c10b9f..6007b3e2 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/Useful_SystemTap_Scripts.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/Useful_SystemTap_Scripts.xml @@ -5,11 +5,11 @@ <chapter id="useful-systemtap-scripts"> <title>Useful SystemTap Scripts</title> - <para>This chapter enumerates several SystemTap scripts you can use to monitor and investigate different subsystems. All of these scripts are available at the following link:</para> - + <para>This chapter enumerates several SystemTap scripts you can use to monitor and investigate different subsystems. All of these scripts are available at <filename>/usr/share/systemtap/testsuite/systemtap.examples/</filename> once you install the <filename>systemtap-testsuite</filename> RPM.</para> +<!-- <para><ulink url="http://sourceware.org/systemtap/examples/subsystem-index.html">http://sourceware.org/systemtap/examples/subsystem-index.html</ulink></para> - + --> <remark> short intro, reference to online source (http://sourceware.org/systemtap/examples/subsystem-index.html); "always updated" </remark> @@ -29,7 +29,8 @@ <xi:include href="Useful_Scripts-inodewatch.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="Useful_Scripts-inodewatch2.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="Useful_Scripts-functioncalls.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> - <xi:include href="Useful_Scripts-kernelprofiling.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> +<!-- removed; handler function no longer working as expected + <xi:include href="Useful_Scripts-kernelprofiling.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> --> <xi:include href="Useful_Scripts-futexes.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="Useful_Scripts-nettop.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> <xi:include href="Useful_Scripts-sockettrace.xml" xmlns:xi="http://www.w3.org/2001/XInclude" /> |