# 帳票設計書 3-iostat - I/O統計レポート

## 概要

本ドキュメントは、FreeBSDシステムにおけるI/O統計レポート(iostat)の帳票設計書である。iostatコマンドはカーネルのdevstat統計情報を読み取り、ディスクI/Oデバイスのスループット、転送回数、レイテンシ、CPU使用率などの統計を定期的にテキスト形式で標準出力に出力する。

### 本帳票の処理概要

**業務上の目的・背景**：システム管理者がディスクI/Oのパフォーマンスを監視し、ボトルネックの特定やストレージ容量計画に役立てるために必要なレポートである。I/Oサブシステムの問題を早期に検知するための重要な監視ツール。

**帳票の利用シーン**：ディスクI/Oパフォーマンスの定期的な監視、ストレージのボトルネック調査、パフォーマンスチューニング時のベースライン計測、トラブルシューティング。

**主要な出力内容**：
1. デバイスごとのKB/転送、転送回数/秒、MB/秒（標準モード）
2. デバイスごとの読み取り/書き込み別統計、レイテンシ、ビジー率（拡張モード: -x）
3. TTY統計（入力/出力文字数）
4. CPU使用率（user/nice/system/interrupt/idle）

**帳票の出力タイミング**：コマンド実行で即時出力。-wオプションで指定間隔での繰り返し出力。-cオプションで指定回数分出力。

**帳票の利用者**：システム管理者、ストレージ管理者、パフォーマンスエンジニア。

## 帳票種別

集計表（テキスト形式のリアルタイムI/O統計レポート）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | ターミナル/コンソール | N/A | `iostat [-CdhIKoTxz] [-c count] [-M core] [-n devs] [-N system] [-t type,if,pass] [-w wait] [drives]` コマンド実行 |

## 出力形式

### 基本仕様

| 項目 | 内容 |
|-----|------|
| ファイル形式 | テキスト（標準出力） |
| 用紙サイズ | N/A |
| 向き | N/A |
| ファイル名 | N/A |
| 出力方法 | 標準出力への直接出力 |
| 文字コード | ASCII |

## 帳票レイアウト

### レイアウト概要

ヘッダー行とデータ行で構成。ヘッダーは端末のウィンドウサイズに応じて繰り返し表示される。

```
┌─────────────────────────────────────────────────────┐
│  ヘッダー行（TTY/デバイス名/CPU）                       │
│  列名行（tin tout / KB/t tps MB/s / us ni sy in id）  │
├─────────────────────────────────────────────────────┤
│  データ行（繰り返し出力）                               │
└─────────────────────────────────────────────────────┘
```

### ヘッダー部（標準モード）

| No | 項目名 | 説明 | データ取得元 | 表示形式 |
|----|-------|------|-------------|---------|
| 1 | tty | TTY統計ヘッダー | 固定 | "tty" (-T時) |
| 2 | デバイス名 | デバイス名+番号 | devinfo.device_name + unit_number | 6文字幅 |
| 3 | cpu | CPU統計ヘッダー | 固定 | "cpu" (-C時) |

### 明細部（標準モード）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | tin | TTY入力文字/秒 | kern.tty_nin (sysctl) | 整数 | 4桁 |
| 2 | tout | TTY出力文字/秒 | kern.tty_nout (sysctl) | 整数 | 5桁 |
| 3 | KB/t | 転送あたりKB | DSM_KB_PER_TRANSFER | 小数点1桁 | 4桁 |
| 4 | tps | 転送/秒 | DSM_TRANSFERS_PER_SECOND | 整数 | 5桁 |
| 5 | MB/s | MB/秒 | DSM_MB_PER_SECOND | 小数点1-2桁 | 5桁 |
| 6 | us | CPU user% | cp_time[CP_USER]+cp_time[CP_NICE] | 整数% | 2桁 |
| 7 | ni | CPU nice% | 含まれるがus内 | 整数% | 2桁 |
| 8 | sy | CPU system% | cp_time[CP_SYS]+cp_time[CP_INTR] | 整数% | 2桁 |
| 9 | in | CPU interrupt% | 含まれるがsy内 | 整数% | 2桁 |
| 10 | id | CPU idle% | cp_time[CP_IDLE] | 整数% | 2桁 |

### 明細部（拡張モード: -xオプション）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | device | デバイス名 | device_name + unit_number | 文字列 | 8桁 |
| 2 | r/s | 読み取り転送/秒 | DSM_TRANSFERS_PER_SECOND_READ | 整数 | 7桁 |
| 3 | w/s | 書き込み転送/秒 | DSM_TRANSFERS_PER_SECOND_WRITE | 整数 | 7桁 |
| 4 | kr/s | 読み取りKB/秒 | DSM_MB_PER_SECOND_READ * 1024 | 小数点1桁 | 8桁 |
| 5 | kw/s | 書き込みKB/秒 | DSM_MB_PER_SECOND_WRITE * 1024 | 小数点1桁 | 8桁 |
| 6 | ms/r | 読み取りレイテンシ(ms) | DSM_MS_PER_TRANSACTION_READ | 整数 | 5桁 |
| 7 | ms/w | 書き込みレイテンシ(ms) | DSM_MS_PER_TRANSACTION_WRITE | 整数 | 5桁 |
| 8 | ms/o | その他レイテンシ(ms) | DSM_MS_PER_TRANSACTION_OTHER | 整数 | 5桁 |
| 9 | ms/t | 合計レイテンシ(ms) | DSM_MS_PER_TRANSACTION | 整数 | 5桁 |
| 10 | qlen | キュー長 | DSM_QUEUE_LENGTH | 整数 | 4桁 |
| 11 | %b | ビジー率 | DSM_BUSY_PCT | 小数点1桁 | 3桁 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| デバイス指定 | コマンドライン引数でデバイス名を指定 | No |
| デバイスタイプ（-t） | type,if,passの形式でデバイスタイプをフィルタ | No |
| -zオプション | I/Oがゼロのデバイスをスキップ | No |

### ソート順

| 優先度 | 項目 | 昇順/降順 |
|-------|------|---------|
| 1 | デバイス選択順 | devstat_selectdevsの優先度順 |

### 改ページ条件

端末行数に基づき、ヘッダーを繰り返し表示（wrows変数、SIGWINCHで動的更新）

## データベース参照仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| devstat (カーネル) | デバイスI/O統計 | devstat_getdevs() API |
| kern.cp_time (sysctl) | CPU時間統計 | sysctlbyname() |
| kern.tty_nin/nout (sysctl) | TTY統計 | sysctlbyname() |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| etime | cur.snap_time - last.snap_time | 長倍精度浮動小数点 | 0の場合1.0に補正 |
| CPU% | 100 * cp_time[state] / total_cptime | rint()で丸め | cpustats関数 |
| TTY文字/秒 | (cur.tk_nin - last.tk_nin) / etime | 整数 | -Tオプション時 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B[オプション解析]
    B --> C[devstat初期化・デバイス選択]
    C --> D[メインループ]
    D --> E[devstat_getdevs: デバイス統計取得]
    E --> F{ヘッダー表示タイミング?}
    F -->|Yes| G[phdr: ヘッダー出力]
    F -->|No| H[devstats: デバイス統計出力]
    G --> H
    H --> I[cpustats: CPU統計出力]
    I --> J{カウント残り?}
    J -->|Yes| K[usleep: 待機]
    K --> D
    J -->|No| L[終了]
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| devstatバージョン不一致 | カーネルとユーザーランドの不一致 | errx(1, "%s", devstat_errbuf) | カーネルとユーティリティの同期 |
| デバイス情報取得失敗 | devstat_getdevs()失敗 | errx(1, "%s", devstat_errbuf) | カーネルモジュール確認 |
| kvm_openfiles失敗 | -M/-Nオプション時のコアファイル | errx(1, ...) | コアファイルパス確認 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | システムのデバイス数に依存（通常数～数十デバイス） |
| 目標出力時間 | リアルタイム出力（指定間隔ごとに即座に表示） |
| 同時出力数上限 | N/A |

## セキュリティ考慮事項

- -M/-Nオプションでカーネルコアファイルを読む場合はkmemグループ権限が必要
- sysctlベースの統計取得は一般ユーザーでも実行可能

## 備考

- -xオプションと-oオプション（旧形式）で出力フォーマットが異なる
- SIGALRMを使用したタイマーベースの待機（setitimer使用、464-468行目）
- SIGINTでの終了時に最終統計を出力（needreturn関数）

---

## コードリーディングガイド

本帳票を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | iostat.c | `usr.sbin/iostat/iostat.c` | 120-133行目: namelistの定義（カーネルシンボル参照用） |
| 1-2 | iostat.c | `usr.sbin/iostat/iostat.c` | 137-148行目: グローバル変数（cur/last statinfo、dev_select等） |

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | iostat.c | `usr.sbin/iostat/iostat.c` | 177-649行目: main関数。オプション解析、デバイス選択、メインループ |

**主要処理フロー**:
1. **201行目**: getoptでオプション解析
2. **284行目**: devstat_checkversion()でバージョン確認
3. **297行目**: devstat_getnumdevs()でデバイス数取得
4. **376行目**: devstat_selectdevs()でデバイス選択
5. **470-646行目**: メインループ（統計取得→表示→待機）

#### Step 3: 出力処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | iostat.c | `usr.sbin/iostat/iostat.c` | 720-780行目: phdr関数（ヘッダー出力） |
| 3-2 | iostat.c | `usr.sbin/iostat/iostat.c` | 782-980行目: devstats関数（デバイス統計出力） |
| 3-3 | iostat.c | `usr.sbin/iostat/iostat.c` | 982-995行目: cpustats関数（CPU統計出力） |

### プログラム呼び出し階層図

```
main() [177行目]
    |
    +-- devstat_checkversion()
    +-- devstat_getnumdevs()
    +-- devstat_getdevs()
    +-- devstat_selectdevs()
    +-- メインループ
           |
           +-- readvar() [997行目] ... sysctl/kvmからの値読み取り
           +-- phdr() [720行目] ... ヘッダー出力
           +-- devstats() [782行目]
           |      +-- devstat_compute_statistics() ... 統計計算
           +-- cpustats() [982行目] ... CPU統計出力
           +-- doresize() [695行目] ... 端末サイズ更新
```

### データフロー図

```
[入力]                        [処理]                        [出力]

devstat (カーネル) ────▶ devstat_getdevs()          ──▶ 標準出力
kern.cp_time (sysctl) ──▶ readvar()                      (テキスト)
kern.tty_nin/nout ──────▶ devstat_compute_statistics()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| iostat.c | `usr.sbin/iostat/iostat.c` | ソース | 全処理が単一ファイルに集約 |
