summaryrefslogtreecommitdiffstats
path: root/tutorialse4.html
blob: 1246e05e5659501e0d70484854637c08faada84d (plain) (blame)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html > <head><title>Tapsets</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <meta name="generator" content="TeX4ht (https://tug.org/tex4ht/)"> <meta name="originator" content="TeX4ht (https://tug.org/tex4ht/)"> <!-- html,2 --> <meta name="src" content="tutorial.tex"> <link rel="stylesheet" type="text/css" href="tutorial.css"> </head><body > <!--l. 756--><div class="crosslinks"><p class="noindent">[<a href="tutorialse3.html" >prev</a>] [<a href="tutorialse3.html#tailtutorialse3.html" >prev-tail</a>] [<a href="tutorialse3.html#tailtutorialse4.html">tail</a>] [<a href="tutorial.html# " >up</a>] </p></div> <h3 class="sectionHead"><span class="titlemark">4 </span> <a id="x10-150004"></a>Tapsets</h3> <!--l. 758--><p class="noindent" >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 (<span class="obeylines-h"><span class="verb"><span class="cmtt-10">pid()</span></span></span>, etc.) used in the scripts above come from tapset scripts like that. A &#8220;tapset&#8221; is just a script that designed for reuse by installation into a special directory. <!--l. 766--><p class="noindent" > <h4 class="subsectionHead"><span class="titlemark">4.1 </span> <a id="x10-160004.1"></a>Automatic selection</h4> <!--l. 768--><p class="noindent" >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 directory named <span class="obeylines-h"><span class="verb"><span class="cmtt-10">/usr/share/systemtap/tapset</span></span></span>. A user may give additional directories with the <span class="obeylines-h"><span class="verb"><span class="cmtt-10">-I</span><span class="cmtt-10">&#x00A0;DIR</span></span></span> option. Systemtap searches these directories for script (<span class="obeylines-h"><span class="verb"><span class="cmtt-10">.stp</span></span></span>) files. <!--l. 776--><p class="noindent" >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&#x00A0;<a href="#x10-160017">7<!--tex4ht:ref: fig:tapset-search --></a>. <!--l. 784--><p class="noindent" ><hr class="figure"><div class="figure" > <a id="x10-160017"></a> <div class="center" > <!--l. 785--><p class="noindent" > <div class="fbox"><div class="minipage"><pre class="verbatim" id="verbatim-9"> #&#x00A0;stap&#x00A0;-p1&#x00A0;-vv&#x00A0;-e&#x00A0;&#8217;probe&#x00A0;begin&#x00A0;{&#x00A0;}&#8217;&#x00A0;&#x003E;&#x00A0;/dev/null Created&#x00A0;temporary&#x00A0;directory&#x00A0;"/tmp/staplnEBh7" Searched&#x00A0;&#8217;/usr/share/systemtap/tapset/2.6.15/i686/*.stp&#8217;,&#x00A0;match&#x00A0;count&#x00A0;0 Searched&#x00A0;&#8217;/usr/share/systemtap/tapset/2.6.15/*.stp&#8217;,&#x00A0;match&#x00A0;count&#x00A0;0 Searched&#x00A0;&#8217;/usr/share/systemtap/tapset/2.6/i686/*.stp&#8217;,&#x00A0;match&#x00A0;count&#x00A0;0 Searched&#x00A0;&#8217;/usr/share/systemtap/tapset/2.6/*.stp&#8217;,&#x00A0;match&#x00A0;count&#x00A0;0 Searched&#x00A0;&#8217;/usr/share/systemtap/tapset/i686/*.stp&#8217;,&#x00A0;match&#x00A0;count&#x00A0;1 Searched&#x00A0;&#8217;/usr/share/systemtap/tapset/*.stp&#8217;,&#x00A0;match&#x00A0;count&#x00A0;12 Pass&#x00A0;1:&#x00A0;parsed&#x00A0;user&#x00A0;script&#x00A0;and&#x00A0;13&#x00A0;library&#x00A0;script(s)&#x00A0;in&#x00A0;350usr/10sys/375real&#x00A0;ms. Running&#x00A0;rm&#x00A0;-rf&#x00A0;/tmp/staplnEBh7 </pre> <!--l. 797--><p class="nopar" > </div></div> </div> <br /> <div class="caption" ><span class="id">Figure&#x00A0;7: </span><span class="content">Listing the tapset search path.</span></div><!--tex4ht:label?: x10-160017 --> <!--l. 801--><p class="noindent" ></div><hr class="endfigure"> <!--l. 803--><p class="noindent" >When a script file is found that <span class="bchri7t-">defines </span>one of the undefined symbols, that <span class="bchri7t-">entire file </span>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. <!--l. 808--><p class="noindent" >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 different kernel <span class="obeylines-h"><span class="verb"><span class="cmtt-10">include/asm/ARCH/</span></span></span> files contain macros that provide a porting layer. <!--l. 816--><p class="noindent" >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&#x00A0;<a href="#x10-160028">8<!--tex4ht:ref: fig:tapset-default --></a> shows a way. <!--l. 825--><p class="noindent" ><hr class="figure"><div class="figure" > <a id="x10-160028"></a> <div class="center" > <!--l. 826--><p class="noindent" > <div class="fbox"><div class="minipage"><pre class="verbatim" id="verbatim-10"> #&#x00A0;cat&#x00A0;tapset/time-common.stp global&#x00A0;__time_vars function&#x00A0;timer_begin&#x00A0;(name)&#x00A0;{&#x00A0;__time_vars[name]&#x00A0;=&#x00A0;__time_value&#x00A0;()&#x00A0;} function&#x00A0;timer_end&#x00A0;(name)&#x00A0;{&#x00A0;return&#x00A0;__time_value()&#x00A0;-&#x00A0;__time_vars[name]&#x00A0;} #&#x00A0;cat&#x00A0;tapset/time-default.stp function&#x00A0;__time_value&#x00A0;()&#x00A0;{&#x00A0;return&#x00A0;gettimeofday_us&#x00A0;()&#x00A0;} #&#x00A0;cat&#x00A0;tapset-time-user.stp probe&#x00A0;begin { &#x00A0;&#x00A0;timer_begin&#x00A0;("bench") &#x00A0;&#x00A0;for&#x00A0;(i=0;&#x00A0;i&#x003C;100;&#x00A0;i++)&#x00A0;; &#x00A0;&#x00A0;printf&#x00A0;("%d&#x00A0;cycles\n",&#x00A0;timer_end&#x00A0;("bench")) &#x00A0;&#x00A0;exit&#x00A0;() } function&#x00A0;__time_value&#x00A0;()&#x00A0;{&#x00A0;return&#x00A0;get_ticks&#x00A0;()&#x00A0;}&#x00A0;#&#x00A0;override&#x00A0;for&#x00A0;greater&#x00A0;precision </pre> <!--l. 846--><p class="nopar" > </div></div> </div> <br /> <div class="caption" ><span class="id">Figure&#x00A0;8: </span><span class="content">Providing an overrideable default.</span></div><!--tex4ht:label?: x10-160028 --> <!--l. 850--><p class="noindent" ></div><hr class="endfigure"> <!--l. 852--><p class="noindent" >A tapset that exports only <span class="bchri7t-">data </span>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. <h4 class="subsectionHead"><span class="titlemark">4.2 </span> <a id="x10-170004.2"></a>Probe point aliases</h4> <!--l. 861--><p class="noindent" >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 form <span class="obeylines-h"><span class="verb"><span class="cmtt-10">syscall.open</span></span></span> etc., in terms of lower level ones like <span class="obeylines-h"><span class="verb"><span class="cmtt-10">kernel.function("sys_open")</span></span></span>. Even if some future kernel renames <span class="obeylines-h"><span class="verb"><span class="cmtt-10">sys_open</span></span></span>, the aliased name can remain valid. <!--l. 869--><p class="noindent" >A probe point alias definition looks like a normal probe. Both start with the keyword <span class="obeylines-h"><span class="verb"><span class="cmtt-10">probe</span></span></span> 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 (<span class="obeylines-h"><span class="verb"><span class="cmtt-10">=</span></span></span>) operator. Another probe that names the new probe point will create an actual probe, with the handler of the alias <span class="bchri7t-">prepended</span>. <!--l. 876--><p class="noindent" >This prepending behavior serves several purposes. It allows the alias definition to &#8220;preprocess&#8221; the context of the probe before passing control to the user-specified handler. This has several possible uses: <!--tex4ht:inline--><div class="tabular"> <table id="TBL-11" class="tabular" ><colgroup id="TBL-11-1g"><col id="TBL-11-1"><col id="TBL-11-2"></colgroup><tr style="vertical-align:baseline;" id="TBL-11-1-"><td style="white-space:nowrap; text-align:right;" id="TBL-11-1-1" class="td11"><span class="obeylines-h"><span class="verb"><span class="cmtt-10">if</span><span class="cmtt-10">&#x00A0;($flag1</span><span class="cmtt-10">&#x00A0;!=</span><span class="cmtt-10">&#x00A0;$flag2)</span><span class="cmtt-10">&#x00A0;next</span></span></span></td><td style="white-space:nowrap; text-align:left;" id="TBL-11-1-2" class="td11">skip probe unless given condition is met </td> </tr><tr style="vertical-align:baseline;" id="TBL-11-2-"><td style="white-space:nowrap; text-align:right;" id="TBL-11-2-1" class="td11"> <span class="obeylines-h"><span class="verb"><span class="cmtt-10">name</span><span class="cmtt-10">&#x00A0;=</span><span class="cmtt-10">&#x00A0;"foo"</span></span></span></td><td style="white-space:nowrap; text-align:left;" id="TBL-11-2-2" class="td11">supply probe-describing values </td> </tr><tr style="vertical-align:baseline;" id="TBL-11-3-"><td style="white-space:nowrap; text-align:right;" id="TBL-11-3-1" class="td11"> <span class="obeylines-h"><span class="verb"><span class="cmtt-10">var</span><span class="cmtt-10">&#x00A0;=</span><span class="cmtt-10">&#x00A0;$var</span></span></span></td><td style="white-space:nowrap; text-align:left;" id="TBL-11-3-2" class="td11">extract target variable to plain local variable</td> </tr><tr style="vertical-align:baseline;" id="TBL-11-4-"><td style="white-space:nowrap; text-align:right;" id="TBL-11-4-1" class="td11"> </td> </tr></table> </div> <!--l. 885--><p class="noindent" >Figure&#x00A0;<a href="#x10-170019">9<!--tex4ht:ref: fig:probe-alias --></a> 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. <!--l. 891--><p class="noindent" ><hr class="figure"><div class="figure" > <a id="x10-170019"></a> <div class="center" > <!--l. 892--><p class="noindent" > <div class="fbox"><div class="minipage"><pre class="verbatim" id="verbatim-11"> #&#x00A0;cat&#x00A0;probe-alias.stp probe&#x00A0;syscallgroup.io&#x00A0;=&#x00A0;syscall.open,&#x00A0;syscall.close, &#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;syscall.read,&#x00A0;syscall.write {&#x00A0;groupname&#x00A0;=&#x00A0;"io"&#x00A0;} probe&#x00A0;syscallgroup.process&#x00A0;=&#x00A0;syscall.fork,&#x00A0;syscall.execve {&#x00A0;groupname&#x00A0;=&#x00A0;"process"&#x00A0;} probe&#x00A0;syscallgroup.* {&#x00A0;groups&#x00A0;[execname()&#x00A0;.&#x00A0;"/"&#x00A0;.&#x00A0;groupname]&#x00A0;++&#x00A0;} probe&#x00A0;end { &#x00A0;&#x00A0;foreach&#x00A0;(eg+&#x00A0;in&#x00A0;groups) &#x00A0;&#x00A0;&#x00A0;&#x00A0;printf&#x00A0;("%s:&#x00A0;%d\n",&#x00A0;eg,&#x00A0;groups[eg]) } global&#x00A0;groups #&#x00A0;stap&#x00A0;probe-alias.stp 05-wait_for_sys/io:&#x00A0;19 10-udev.hotplug/io:&#x00A0;17 20-hal.hotplug/io:&#x00A0;12 X/io:&#x00A0;73 apcsmart/io:&#x00A0;59 [...] make/io:&#x00A0;515 make/process:&#x00A0;16 [...] xfce-mcs-manage/io:&#x00A0;3 xfdesktop/io:&#x00A0;5 [...] xmms/io:&#x00A0;7070 zsh/io:&#x00A0;78 zsh/process:&#x00A0;5 </pre> <!--l. 929--><p class="nopar" > </div></div> </div> <br /> <div class="caption" ><span class="id">Figure&#x00A0;9: </span><span class="content">Classified system call activity.</span></div><!--tex4ht:label?: x10-170019 --> <!--l. 933--><p class="noindent" ></div><hr class="endfigure"> <h4 class="subsectionHead"><span class="titlemark">4.3 </span> <a id="x10-180004.3"></a>Embedded C</h4> <!--l. 938--><p class="noindent" >Sometimes, a tapset needs provide data values from the kernel that cannot be extracted using ordinary target variables (<span class="obeylines-h"><span class="verb"><span class="cmtt-10">$var</span></span></span>). 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 &#8220;escape hatch&#8221; 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&#x00A0;<a href="tutorialse3.html#x6-130003.6">3.6<!--tex4ht:ref: sec:safety --></a>. End-user scripts <span class="bchri7t-">may not </span>include embedded C code, unless systemtap is run with the <span class="obeylines-h"><span class="verb"><span class="cmtt-10">-g</span></span></span> (&#8220;guru&#8221; mode) option. Tapset scripts get guru mode privileges automatically. <!--l. 951--><p class="noindent" >Embedded C can be the body of a script function. Instead enclosing the function body statements in <span class="obeylines-h"><span class="verb"><span class="cmtt-10">{</span></span></span> and <span class="obeylines-h"><span class="verb"><span class="cmtt-10">}</span></span></span>, use <span class="obeylines-h"><span class="verb"><span class="cmtt-10">%{</span></span></span> and <span class="obeylines-h"><span class="verb"><span class="cmtt-10">%}</span></span></span>. 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 <span class="obeylines-h"><span class="verb"><span class="cmtt-10">STAP_ARG_*</span></span></span> and <span class="obeylines-h"><span class="verb"><span class="cmtt-10">STAP_RETVALUE</span></span></span> are made available. The familiar data-gathering functions <span class="obeylines-h"><span class="verb"><span class="cmtt-10">pid()</span></span></span>, <span class="obeylines-h"><span class="verb"><span class="cmtt-10">execname()</span></span></span>, and their neighbours are all embedded C functions. Figure&#x00A0;<a href="#x10-1801110">10<!--tex4ht:ref: fig:embedded-C --></a> contains another example. <!--l. 961--><p class="noindent" >Since systemtap cannot examine the C code to infer these types, an optional<span class="footnote-mark"><a href="tutorial11.html#fn5x0"><sup class="textsuperscript">5</sup></a></span><a id="x10-18001f5"></a> annotation syntax is available to assist the type inference process. Simply suffix parameter names and/or the function name with <span class="obeylines-h"><span class="verb"><span class="cmtt-10">:string</span></span></span> or <span class="obeylines-h"><span class="verb"><span class="cmtt-10">:long</span></span></span> to designate the string or numeric type. In addition, the script may include a <span class="obeylines-h"><span class="verb"><span class="cmtt-10">%{</span></span></span> <span class="obeylines-h"><span class="verb"><span class="cmtt-10">%}</span></span></span> block at the outermost level of the script, in order to transcribe declarative code like <span class="obeylines-h"><span class="verb"><span class="cmtt-10">#include</span><span class="cmtt-10">&#x00A0;&#x003C;linux/foo.h&#x003E;</span></span></span>. These enable the embedded C functions to refer to general kernel types. <!--l. 972--><p class="noindent" >There are a number of safety-related constraints that should be observed by developers of embedded C code. <ol class="enumerate1" > <li class="enumerate" id="x10-18004x1"> <!--l. 975--><p class="noindent" >Do not dereference pointers that are not known or testable valid. </li> <li class="enumerate" id="x10-18006x2"> <!--l. 976--><p class="noindent" >Do not call any kernel routine that may cause a sleep or fault. </li> <li class="enumerate" id="x10-18008x3"> <!--l. 977--><p class="noindent" >Consider possible undesirable recursion, where your embedded C function calls a routine that may be the subject of a probe. If that probe handler calls your embedded C function, you may suffer infinite regress. Similar problems may arise with respect to non-reentrant locks. </li> <li class="enumerate" id="x10-18010x4"> <!--l. 982--><p class="noindent" >If locking of a data structure is necessary, use a <span class="obeylines-h"><span class="verb"><span class="cmtt-10">trylock</span></span></span> type call to attempt to take the lock. If that fails, give up, do not block.</li></ol> <!--l. 987--><p class="noindent" ><hr class="figure"><div class="figure" > <a id="x10-1801110"></a> <div class="center" > <!--l. 988--><p class="noindent" > <div class="fbox"><div class="minipage"><pre class="verbatim" id="verbatim-12"> #&#x00A0;cat&#x00A0;embedded-C.stp %{ #include&#x00A0;&#x003C;linux/sched.h&#x003E; #include&#x00A0;&#x003C;linux/list.h&#x003E; %} function&#x00A0;task_execname_by_pid:string&#x00A0;(pid:long)&#x00A0;%{ &#x00A0;&#x00A0;struct&#x00A0;task_struct&#x00A0;*p; &#x00A0;&#x00A0;struct&#x00A0;list_head&#x00A0;*_p,&#x00A0;*_n; &#x00A0;&#x00A0;list_for_each_safe(_p,&#x00A0;_n,&#x00A0;&amp;current-&#x003E;tasks)&#x00A0;{ &#x00A0;&#x00A0;&#x00A0;&#x00A0;p&#x00A0;=&#x00A0;list_entry(_p,&#x00A0;struct&#x00A0;task_struct,&#x00A0;tasks); &#x00A0;&#x00A0;&#x00A0;&#x00A0;if&#x00A0;(p-&#x003E;pid&#x00A0;==&#x00A0;(int)STAP_ARG_pid) &#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;&#x00A0;snprintf(STAP_RETVALUE,&#x00A0;MAXSTRINGLEN,&#x00A0;"%s",&#x00A0;p-&#x003E;comm); &#x00A0;&#x00A0;} %} probe&#x00A0;begin { &#x00A0;&#x00A0;printf("%s(%d)\n",&#x00A0;task_execname_by_pid(target()),&#x00A0;target()) &#x00A0;&#x00A0;exit() } #&#x00A0;pgrep&#x00A0;emacs 16641 #&#x00A0;stap&#x00A0;-g&#x00A0;embedded-C.stp&#x00A0;-x&#x00A0;16641 emacs(16641) </pre> <!--l. 1016--><p class="nopar" > </div></div> </div> <br /> <div class="caption" ><span class="id">Figure&#x00A0;10: </span><span class="content">Embedded C function.</span></div><!--tex4ht:label?: x10-1801110 --> <!--l. 1020--><p class="noindent" ></div><hr class="endfigure"> <h4 class="subsectionHead"><span class="titlemark">4.4 </span> <a id="x10-190004.4"></a>Naming conventions</h4> <!--l. 1024--><p class="noindent" >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. <!--l. 1030--><p class="noindent" >To control this problem, systemtap tapset developers are advised to follow naming conventions. Here is some of the guidance. <ol class="enumerate1" > <li class="enumerate" id="x10-19002x1"> <!--l. 1035--><p class="noindent" >Pick a unique name for your tapset, and substitute it for <span class="bchri7t-">TAPSET </span>below. </li> <li class="enumerate" id="x10-19004x2"> <!--l. 1037--><p class="noindent" >Separate identifiers meant to be used by tapset users from those that are internal implementation artifacts. </li> <li class="enumerate" id="x10-19006x3"> <!--l. 1039--><p class="noindent" >Document the first set in the appropriate <span class="obeylines-h"><span class="verb"><span class="cmtt-10">man</span></span></span> pages. </li> <li class="enumerate" id="x10-19008x4"> <!--l. 1040--><p class="noindent" >Prefix the names of external identifiers with <span class="bchri7t-">TAPSET</span>_ if there is any likelihood of collision with other tapsets or end-user scripts. </li> <li class="enumerate" id="x10-19010x5"> <!--l. 1043--><p class="noindent" >Prefix any probe point aliases with an appropriate prefix. </li> <li class="enumerate" id="x10-19012x6"> <!--l. 1044--><p class="noindent" >Prefix the names of internal identifiers with __<span class="bchri7t-">TAPSET</span>_.</li></ol> <!--l. 1047--><p class="noindent" > <h4 class="subsectionHead"><span class="titlemark">4.5 </span> <a id="x10-200004.5"></a>Exercises</h4> <!--l. 1049--><p class="noindent" > <ol class="enumerate1" > <li class="enumerate" id="x10-20002x1"> <!--l. 1050--><p class="noindent" >Write a tapset that implements deferred and &#8220;cancelable&#8221; logging. Export a function that enqueues a text string (into some private array), returning an id token. Include a timer-based probe that periodically flushes the array to the standard log output. Export another function that, if the entry was not already flushed, allows a text string to be cancelled from the queue. One might speculate that similar functions and tapsets exist. </li> <li class="enumerate" id="x10-20004x2"> <!--l. 1058--><p class="noindent" >Create a &#8220;relative timestamp&#8221; tapset with functions return all the same values as the ones in the timestamp tapset, except that they are made relative to the start time of the script. </li> <li class="enumerate" id="x10-20006x3"> <!--l. 1062--><p class="noindent" >Create a tapset that exports a global array that contains a mapping of recently seen process ID numbers to process names. Intercept key system calls (<span class="obeylines-h"><span class="verb"><span class="cmtt-10">execve</span></span></span>?) to update the list incrementally. </li> <li class="enumerate" id="x10-20008x4"> <!--l. 1067--><p class="noindent" >Send your tapset ideas to the mailing list!</li></ol> <!--l. 1070--><div class="crosslinks"><p class="noindent">[<a href="tutorialse3.html" >prev</a>] [<a href="tutorialse3.html#tailtutorialse3.html" >prev-tail</a>] [<a href="tutorialse4.html" >front</a>] [<a href="tutorial.html# " >up</a>] </p></div> <!--l. 1070--><p class="noindent" ><a id="tailtutorialse4.html"></a> </body></html>