機械翻訳について

IOプロバイダ

ioプロバイダは、ディスク入出力に関連したプローブを使用可能にします。

たとえばioプロバイダを使用して、デバイス、I/Oの種類、I/Oサイズ、プロセス、アプリケーション名を基準にI/Oを確認できます。

ioプローブ

次の表に、ioプロバイダのプローブを示します。 すべてのioプローブについて、モジュールはvmlinuxで、関数は空の文字列です。

表9-3 ioプローブ

プローブ 説明

start

周辺機器またはNFSサーバーに対してI/Oリクエストが発行される直前に起動します。

done

I/Oリクエストが満たされた後に起動します。 doneプローブは、I/Oが完了してから完了処理がバッファ上で実行されるまでの間に起動します。 B_DONEは、完了したプローブの起動時にb_flagsに設定されません。

wait-start

スレッドがI/Oリクエストの完了を待機する直前に起動します。 wait-startプローブの起動後しばらくすると、同じスレッドでwait-doneプローブが起動します。

wait-done

スレッドがI/Oリクエストの完了の待機を終了したときに起動します。 wait-doneプローブは常に、同じスレッドでwait-startプローブが起動した後に起動します。

ioプローブは、周辺機器に対するI/Oリクエストが発行されたときと、NFSサーバーに対するファイルの読取り/書込みリクエストが発行されたときに起動します。 たとえば、NFSサーバーからのメタデータのリクエストは、readdir()リクエストのためにioプローブをトリガーしません。

ioプローブの引数

次の表では、ioプローブの引数について説明します。 argNは実装固有です。 args[]を使用して、プローブ引数にアクセスします。

表9-4 ioプローブの引数

プローブ args[0] args[1] args[2]

start

bufinfo_t *

devinfo_t *

fileinfo_t *

done

bufinfo_t *

devinfo_t *

fileinfo_t *

wait-start

bufinfo_t *

devinfo_t *

fileinfo_t *

wait-done

bufinfo_t *

devinfo_t *

fileinfo_t *

ノート:

DTraceは、fileinfo_tioプローブとともに使用するオプションを提供しません。 Oracle Linuxでは、ioプローブがI/Oリクエストが発生したファイルに関して起動するレベルでは情報にアクセスできません。

bufinfo_t

bufinfo_t構造体は、I/Oリクエストについて説明する抽象化オブジェクトです。 I/Oリクエストに対応するバッファは、startdonewait-startおよびwait-doneプローブのargs[0]によってポイントされます。 このデータ構造体の詳細は、/usr/lib64/dtrace/version/io.dを参照してください。 bufinfo_tの定義は、次のとおりです。

typedef struct bufinfo {
  int b_flags;         /* flags */
  size_t b_bcount;     /* number of bytes */
  caddr_t b_addr;      /* buffer address */
  uint64_t b_lblkno;   /* logical block # on device */
  uint64_t b_blkno;    /* expanded block # on device */
  size_t b_resid;      /* not supported */
  size_t b_bufsize;    /* size of allocated buffer */
  caddr_t b_iodone;    /* I/O completion routine */
  int b_error;         /* not supported */
  dev_t b_edev;        /* extended device */
} bufinfo_t;

ノート:

DTraceは、カーネル・バージョンに応じて、Oracle Linux I/Oリクエスト構造に対するbuffer_headまたはbioからbufinfo_tのメンバーを変換します。

b_flagsはI/Oバッファの状態を表し、ビット単位または各種の状態値で構成されます。 次の表では、状態の値について説明します。

表9-5 b_flags値

b_flags 説明

B_ASYNC

0x000400

I/Oリクエストが非同期であり、待機していないことを示します。 wait-startプローブおよびwait-doneプローブは、非同期I/Oリクエストに対して起動しません。

一部のI/Oから非同期とダイレクトされた場合、B_ASYNCが設定されないことがあります。 非同期I/Oサブシステムは、個別のワーカー・スレッドに同期I/O操作を実行させることで、非同期リクエストを実装できます。

B_BUSY

0x000001

 

B_DONE

0x000002

 

B_ERROR

0x000004

 

B_PAGEIO

0x000010

ページングされたI/Oリクエストでバッファが使用されていることを示します。

B_PHYS

0x000020

バッファがユーザー・データ領域への物理(直接)I/Oに使用されていることを示します。

B_READ

0x000040

データが周辺機器からメイン・メモリーへ読み込まれることを示します。

B_WRITE

0x000100

データがメイン・メモリーから周辺機器へ転送されることを示します。

b_bcount: I/Oリクエストの一部として転送されるバイト数です。

b_addr: I/Oリクエストの仮想アドレス(判明している場合)。

b_lblkno: デバイス上のどの論理ブロックにアクセスするかを識別します。 論理ブロックから物理ブロック(シリンダ、トラックなど)へのマッピングは、デバイスごとに定義されています。

b_blkno: デバイス上のどのブロックにアクセスするかを識別します。

b_bufsize: 割り当てられたバッファのサイズです。

b_iodone: I/Oの完了時にコールされるカーネル内の特定のルーチンを識別します。

b_edev: アクセスされたデバイスのメジャー・デバイス番号とマイナー・デバイス番号が含まれます。 Dのサブルーチンgetmajorgetminorを使用すると、b_edevフィールドからメジャーおよびマイナーのデバイス番号を抽出できます。

devinfo_t

devinfo_t構造体は、デバイスに関する情報を提供します。 I/Oの宛先デバイスに対応するdevinfo_t構造体は、startdonewait-startおよびwait-doneプローブでargs[1]によってポイントされます。 このデータ構造体の詳細は、/usr/lib64/dtrace/version/io.dを参照してください。 devinfo_tの定義は、次のとおりです。

typedef struct devinfo {
  int dev_major;           /* major number */
  int dev_minor;           /* minor number */
  int dev_instance;        /* not supported */
  string dev_name;         /* name of device */
  string dev_statname;     /* name of device + instance/minor */
  string dev_pathname;     /* pathname of device */
} devinfo_t;

ノート:

DTraceは、devinfo_tのメンバーを、Oracle Linux I/Oリクエスト構造体のbuffer_headから変換します。

dev_major: デバイスのメジャー番号です。

dev_minor: デバイスのマイナー番号です。

dev_name: デバイスを管理するデバイス・ドライバの名前です。

dev_statname: iostatによってレポートされるデバイスの名前です。 このフィールドは、異常なiostatの出力を実際のI/Oアクティビティに迅速に対応付けるために提供されています。

dev_pathname: デバイスのフルパスです。 dev_pathnameで指定されたパスには、デバイス・ノード、インスタンス番号およびマイナー・ノードを表すコンポーネントが含まれます。 ただし、これらの3つの要素はすべて、必ずしも統計名で表されるわけではありません。 デバイスによっては、統計名がデバイス名とインスタンス番号で構成されている場合もあります。 あるいは、デバイス名とマイナー・ノード番号で構成されている場合もあります。 したがって、同じdev_statname mighを持つ2つのデバイスは、dev_pathnameで異なります。

fileinfo_t

ノート:

Oracle Linuxでは、ioプローブのfileinfo_t引数args[2]はサポートされていません。 ただし、fileinfo_t構造体を使用すると、組込み変数fds[]配列を使用して、プロセスのオープン・ファイルに関する情報を取得できます。

fileinfo_t構造体は、ファイルに関する情報を提供します。 ファイル情報が存在するかどうかは、I/Oリクエストをディスパッチするときにこの情報を提供するファイル・システムによって決まります。 一部のファイル・システム、特にサードパーティのファイル・システムには、この情報を提供しないものもあります。 また、I/Oリクエストの発行元であるファイル・システムにファイル情報が存在しない場合もあります。 たとえば、ファイル・システム・メタデータとの間のI/Oは、いずれのファイルにも関連付けられません。 さらに、高度に最適化されたファイル・システムは、複数の無関係なファイルからのI/Oを集積して、単一のI/Oリクエストを生成することがあります。 この場合、ファイル・システムは、ほとんどのI/Oを表すファイルまたは一部のI/Oを表すファイルのファイル情報を提供することがあります。 または、この場合はファイルシステムがファイル情報をまったく提供しない可能性があります。

このデータ構造体の詳細は、/usr/lib64/dtrace/version/io.dを参照してください。 fileinfo_tの定義は、次のとおりです。

typedef struct fileinfo {
  string fi_name;           /* basename */
  string fi_dirname;        /* not supported */
  string fi_pathname;       /* not supported */
  loff_t fi_offset;         /* offset within file */
  string fi_fs;             /* file system */
  string fi_mount;          /* not supported */
  int fi_oflags;            /* open() flags for file descriptor */
} fileinfo_t;

fi_nameフィールドにはファイルの名前が含まれますが、ディレクトリ・コンポーネントは含まれません。 ファイル情報がI/Oに関連付けられていない場合、fi_nameフィールドは文字列<none>に設定されます。 まれに、ファイルに関連付けられているパス名が不明になることがあります。 この場合、fi_nameフィールドは文字列<unknown>に設定されます。

fi_dirnameフィールドには、ファイル名のディレクトリ・コンポーネントのみが含まれています。 fi_nameと同様に、この文字列は、ファイル情報が存在しない場合は<none>、ファイルに関連付けられているパス名が不明な場合は<unknown>に設定できます。

fi_pathnameフィールドには、ファイルに対するフル・パス名が含まれています。 fi_nameと同様に、この文字列は、ファイル情報が存在しない場合は<none>、ファイルに関連付けられているパス名が不明な場合は<unknown>に設定できます。

fi_offsetフィールドには、ファイル内のオフセット、またはファイル情報が存在しない場合、またはオフセットがファイル・システムによって指定されていない場合、-1が含まれます。

fi_fsフィールドには、ファイル・システムのタイプ、または情報がない場合は<none>,が含まれています。

fi_oflagsフィールドには、ファイルを開くときに指定されたフラグが含まれています。

ioの例

次のサンプル・スクリプトは、発行されるすべてのI/Oの情報を表示します。 次のソース・コードを入力し、iosnoop.dという名前のファイルに保存します。

#pragma D option quiet

BEGIN
{
  printf("%10s %2s\n", "DEVICE", "RW");
}

io:::start
{
  printf("%10s %2s\n", args[1]->dev_statname,
  args[0]->b_flags & B_READ ? "R" : "W");
}

このスクリプトからの出力は、次のようになります:

    DEVICE RW
     dm-00  R
     dm-00  R
     dm-00  R
     dm-00  R
     dm-00  R
     dm-00  R
...

次の例に示すように、連想配列を使用して各I/Oに要した時間(ミリ秒)を追跡することによって、スクリプト例を少し高度にすることができます:

#pragma D option quiet

BEGIN
{
  printf("%10s %2s %7s\n", "DEVICE", "RW", "MS");
}

io:::start
{
  start[args[0]->b_edev, args[0]->b_blkno] = timestamp;
}

io:::done
/start[args[0]->b_edev, args[0]->b_blkno]/
{
  this->elapsed = timestamp - start[args[0]->b_edev, args[0]->b_blkno];
  printf("%10s %2s %3d.%03d\n", args[1]->dev_statname,
  args[0]->b_flags & B_READ ? "R" : "W",
  this->elapsed / 10000000, (this->elapsed / 1000) % 1000);
  start[args[0]->b_edev, args[0]->b_blkno] = 0;
}

変更されたスクリプトは、出力にMS (ミリ秒)列を追加します。

次の例に示すように、デバイス、アプリケーション、プロセスIDおよび転送されたバイトを集計し、whoio.dという名前のファイルに保存できます:

#pragma D option quiet

io:::start
{
  @[args[1]->dev_statname, execname, pid] = sum(args[0]->b_bcount);
}

END
{
  printf("%10s %20s %10s %15s\n", "DEVICE", "APP", "PID", "BYTES");
  printa("%10s %20s %10d %15@d\n", @);
}

このスクリプトを数秒間実行すると、次のような出力になります:

    DEVICE                  APP        PID           BYTES
     dm-00               evince      14759           16384
     dm-00          flush-252:0       1367           45056
     dm-00                 bash      14758          131072
     dm-00       gvfsd-metadata       2787          135168
     dm-00               evince      14758          139264
     dm-00               evince      14338          151552
     dm-00          jbd2/dm-0-8        390          356352

あるデバイスから別のデバイスにデータをコピーする場合は、いずれかのデバイスがコピーのリミッタとして機能するかどうかを知りたい場合があります。 この質問に回答するには、各デバイスで転送される1秒当たりのバイト数ではなく、各デバイスの有効なスループットを知る必要があります。 試験では、次のスクリプトを使用してスループットをcopy.dという名前のファイルに保存することで、スループットを確認できます:

#pragma D option quiet

io:::start
{
  start[args[0]->b_edev, args[0]->b_blkno] = timestamp;
}

io:::done
/start[args[0]->b_edev, args[0]->b_blkno]/
{
  /*
   * We want to get an idea of our throughput to this device in KB/sec.
   * What we have, however, is nanoseconds and bytes. That is we want
   * to calculate:
   *
   * bytes / 1024
   * ------------------------
   * nanoseconds / 1000000000
   *
   * But we cannot calculate this using integer arithmetic without losing
   * precision (the denominator, for one, is between 0 and 1 for nearly
   * all I/Os). So we restate the fraction, and cancel:
   *
   * bytes       1000000000      bytes       976562
   * --------- * ------------- = --------- * -------------
   * 1024        nanoseconds     1           nanoseconds
   *
   * This is easy to calculate using integer arithmetic.
   */
  this->elapsed = timestamp - start[args[0]->b_edev, args[0]->b_blkno];
  @[args[1]->dev_statname, args[1]->dev_pathname] =
    quantize((args[0]->b_bcount * 976562) / this->elapsed);
  start[args[0]->b_edev, args[0]->b_blkno] = 0;
}

END
{
  printa(" %s (%s)\n%@d\n", @);
}

ハード・ディスクからUSBドライブにデータをコピーする際に、前のスクリプトを数秒間実行すると、次のような出力が得られます:

sdc1 (/dev/sdc1)

           value  ------------- Distribution ------------- count    
              32 |                                         0
              64 |                                         3
             128 |                                         1
             256 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@  2257
             512 |                                         1
            1024 |                                         0       

 dm-00 (/dev/dm-00)

           value  ------------- Distribution ------------- count    
             128 |                                         0
             256 |                                         1
             512 |                                         0
            1024 |                                         2
            2048 |                                         0
            4096 |                                         2
            8192 |@@@@@@@@@@@@@@@@@@                       172
           16384 |@@@@@                                    52
           32768 |@@@@@@@@@@@                              108
           65536 |@@@                                      34
          131072 |                                         0     

前述の出力は、USBドライブ(sdc1)がデバイスの制限を明確にしていることを示しています。 sdc1のスループットは256K/秒から512K/秒の間で、dm-00は8MB/秒から64MB/秒超までのいずれかでI/Oを提供しています。

ioの安定性

ioプロバイダは、DTraceの安定性メカニズムを使用してその安定性を記述します。 これらの値を次の表に示します。

要素 名前の安定性 データの安定性 依存クラス

プロバイダ

発展中

発展中

ISA

モジュール

非公開

非公開

不明

関数

非公開

非公開

不明

名前

発展中

発展中

ISA

引数

発展中

発展中

ISA