1. hana_shin

    No comment

    hana_shin
Changes in body
Source | HTML | Preview
@@ -1,382 +1,381 @@
#1 はじめに
systemtapの使い方の続編です。
インストール方法やその他の使い方は、下記を参照ください。
[SystemTapの使い方](https://qiita.com/hana_shin/items/9b265b4f9a51f98d0f4d)
[SystemTapの使い方(グルモード編)](https://qiita.com/hana_shin/items/f2806e68493c89fbbef8)
[SystemTapの使い方(User-Space Probing)](https://qiita.com/hana_shin/items/6bca693206bf5f887cb3)
[SystemTapの使い方(tapset編)](https://qiita.com/hana_shin/items/0f82ea9d8bc8ed5fd70b)
本記事の説明は、説明を簡単にするため、すべて`begin`プローブ内でスクリプトを実行しました。
本記事の説明は、`begin`以外の`end`プローブ内や本体の部分でも実行できます。
#2 環境
-VMware Workstation 14 Player上の仮想マシンを使いました。
VMware Workstation 14 Playerで作成した仮想マシンを使用しました。
仮想マシンのOS版数は以下のとりです。
```console:OS版数
[root@server ~]# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core)
[root@server ~]# uname -r
3.10.0-957.el7.x86_64
```
#3 連想配列(Associative arrays)の使い方
連想配列とは、添え字にスカラー数値以外のデータ型(文字列型等)も使用できる配列のことです。
SystemTapの連想配列の構文は、`配列名[インデックス]`になります。
さらに、インデックスはカンマ区切りで最大9個までの値を指定できます。
たとえば、`test["Hello"]`や`foo[1,2,3,4,5,6,7,8,9]`のような配列を定義することができます。
##3.1 連想配列への値の代入方法、参照方法
配列testに10、配列fooに20を代入します。
そして、代入した値を表示してみます。
```console:サンプル
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
global foo
probe begin
{
test["Hello"] = 10
foo[1,2,3,4,5,6,7,8,9] = 20
printf("test=%d,foo=%d\n",test["Hello"], foo[1,2,3,4,5,6,7,8,9])
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
test=10,foo=20
```
##3.2 連想値(associated value)のインクリメント、デクリメント
配列testに10、配列fooに20を代入します。
次に、testは1インクリメント、fooは1デクリメントします。
そして、連想値を表示してみます。
```console:サンプル
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
global foo
probe begin
{
test["Hello"] = 10
foo[1,2,3,4,5,6,7,8,9] = 20
printf("test=%d,foo=%d\n",test["Hello"], foo[1,2,3,4,5,6,7,8,9])
test["Hello"] ++
foo[1,2,3,4,5,6,7,8,9] --
printf("test=%d,foo=%d\n",test["Hello"], foo[1,2,3,4,5,6,7,8,9])
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
test=10,foo=20
test=11,foo=19
```
##3.3 繰り返しの使い方(foreach)
```console:サンプル
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test[1, "Hello"] = 30
test[2, "Hello"] = 10
test[3, "Hello"] = 20
foreach ([a,b] in test) {
printf("a=%d,b=%s,test=%d\n",a,b,test[a,b])
}
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
a=1,b=Hello,test=30
a=2,b=Hello,test=10
a=3,b=Hello,test=20
```
##3.4 繰り返しの使い方(降順に表示する方法)
配列testの第1インデックスをキーに降順に連想値を表示してみます。
降順に表示するため、`[a,b]`を`[a-,b]`に変更します。
```console:サンプル(その1)
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test[1, "Hello"] = 30
test[2, "Hello"] = 10
test[3, "Hello"] = 20
foreach ([a-,b] in test) {
printf("a=%d,b=%s,test=%d\n",a,b,test[a,b])
}
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
a=3,b=Hello,test=20
a=2,b=Hello,test=10
a=1,b=Hello,test=30
```
今度は、配列testの連想値をキーに降順に連想値を表示してみます。
降順に表示するため、`test`を`test-`に変更します。
```console:サンプル(その2)
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test[1, "Hello"] = 30
test[2, "Hello"] = 10
test[3, "Hello"] = 20
foreach ([a,b] in test-) {
printf("a=%d,b=%s,test=%d\n",a,b,test[a,b])
}
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
a=1,b=Hello,test=30
a=3,b=Hello,test=20
a=2,b=Hello,test=10
```
##3.5 連想配列がキーを持つかどうかを判定する方法
```console:サンプル
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test[1, "Hello"] = 30
test[2, "Hello"] = 10
test[3, "Hello"] = 20
if([1,"Hello"] in test)
printf("1000\n")
if([2,"Hello"] in test)
printf("2000\n")
if([3,"Hello"] in test)
printf("3000\n")
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
1000
2000
3000
```
#4 統計集計 (Statistical Aggregates) の使い方
統計集計に値を追加するには、演算子`<<<`を使用します。
##4.1 個数を求める方法(`@count`)
配列testに10を代入してみます。
```console:スクリプト(個数が1個の場合)
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test[100] <<< 10
printf("count=%d\n", @count(test[100]))
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
count=1
```
配列testに10と20を代入してみます。
```console:スクリプト(個数が2個の場合)
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test[100] <<< 10
test[100] <<< 20
printf("count=%d\n", @count(test[100]))
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
count=2
```
##4.2 最小(`@min`)、最大(`@max`)、平均(`@avg`)、合計(`@sum`)、を求める方法
```console:スクリプト
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test["hello"] <<< 10
test["hello"] <<< 20
test["hello"] <<< 30
printf("count=%d,min=%d,max=%d,avg=%d,sum=%d\n",
@count(test["hello"]),
@min(test["hello"]),
@max(test["hello"]),
@avg(test["hello"]),
@sum(test["hello"])
)
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
count=3,min=10,max=30,avg=20,sum=60
```
#5 ヒストグラフの描き方( Histogram extractors)
ヒストグラムの書き方を以下に示します。
##5.1 hist_linearの使い方(`@hist_linear`)
```console:スクリプト
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test <<< 100
test <<< 110
test <<< 700
print(@hist_linear(test, 0, 1000, 50))
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
value |-------------------------------------------------- count
0 | 0
50 | 0
100 |@@ 2
150 | 0
200 | 0
~
600 | 0
650 | 0
700 |@ 1
750 | 0
800 | 0
```
##5.2 hist_logの使い方(`@hist_log`)
```console:スクリプト
[root@server ~]# cat tp.stp
#!/usr/bin/stap
global test
probe begin
{
test <<< 100
test <<< 110
test <<< 700
print(@hist_log(test))
delete test
exit()
}
```
```console:実行結果
[root@server ~]# stap tp.stp
value |-------------------------------------------------- count
16 | 0
32 | 0
64 |@@ 2
128 | 0
256 | 0
512 |@ 1
1024 | 0
2048 | 0
```
#Z 参考情報
[3.5. SYSTEMTAP でのアレイ演算](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/systemtap_beginners_guide/arrayoperators)
[SystemTap Language Reference](https://sourceware.org/systemtap/langref.pdf)
[mmitouの日記](https://mmitou.hatenadiary.org/entry/20120721/1342879187)
[SystemTap 3.2 SystemTap Beginners Guide](https://lrita.github.io/images/posts/systemtap/SystemTap_Beginners_Guide.pdf)