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
|
/*
* Linux DTrace
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
#!/usr/sbin/dtrace -s
/*
* NAME
* var-scope.d - initialize, update and print variables
*
* SYNOPSIS
* sudo ./var-scope.d -c <target>
*
* DESCRIPTION
* This script demonstrates some of the scoping rules. It
* shows the behaviour of global and clause-local variables.
* The target can be an application, or any command.
*
* NOTES
* - Other than the BEGIN and END probe used here, there are
* 2 more probes for the fopen() function, but you can use any
* probe you like, or no additional probes at all. You are
* encouraged to experiment with this example and make changes.
*
* - In case this example is used with the date command, you will
* see something like this:
*
* $ sudo ./var-scope.d -c date
* In BEGIN
* A = 10 B = 20
* this->C = 60
* In fopen - return
* A = 11 B = 21
* <output from the date command>
* In END
* A = 11 B = 21
* $
* - Thread-local variables are not demonstrated here, but many
* of the other examples, like io-stats.d, make extensive use
* of them. Please check one of those scripts if you would like
* to learn more how to use thread-local variables.
*
* - Below, the workings of each probe is explained. Since the
* results depend on the command that is traced, we base the
* explanations on the output from the example above.
*/
/*
* Suppress the default output from the dtrace command.
*/
#pragma D option quiet
/*
* This demonstrates how to declare a variable outside of a clause.
* Variable B is declared to be of type int64_t. This is a global
* variable. It is initialized to zero by default.
*/
int64_t B;
/*
* In this clause for the BEGIN probe, A is initialized to 10 and B
* is given a value of 20. Both are global variables. Variable C is
* a clause-local variable initialized to 30.
*/
BEGIN
{
A = 10;
B = 20;
this->C = 30;
}
/*
* In this clause for the BEGIN probe, clause-local variable C is updated
* to a value of 60. This demonstrates that clause-local variables are
* local to the set of clauses executed for a particular probe firing.
* This set is executed in the order they appear in the program.
*
* Here, there are 2 clauses for the BEGIN probe. The printed values
* in the example above confirm this update for C, as well as the initial
* values for A and B.
*/
BEGIN
{
this->C += 30;
printf("In %s\n",probename);
printf("\tA = %d B = %d\n",A,B);
printf("\tthis->C = %d\n",this->C);
}
/*
* The clause in this probe updates A. Since this is a global variable,
* this change is visible to all probes that fire after this probe has fired.
*/
pid$target::fopen:entry
{
A += 1;
}
/*
* The clause in this probe updates B and prints both A and B. The
* probefunc (fopen) and probename (return) are printed first, followed by
* the values for A and B.
* We are in the return probe here, so we know that the entry probe has
* fired too. This means that A has been updated as well.
* This is exactly what we see in the output above: A is 11 and B is 21,
* as it has just been updated.
* Note that C is not visible here, because it is local to the BEGIN probe.
*/
pid$target::fopen:return
{
B += 1;
printf("In %s - %s\n",probefunc,probename);
printf("\tA = %d B = %d\n",A,B);
}
/*
* Both A and B are global variables and are visible in the END probe. The
* final values are printed here.
*/
END
{
printf("In %s\n",probename);
printf("\tA = %d B = %d\n",A,B);
}
|