# 帳票設計書 6-pstat - プロセス・スワップ・TTY統計レポート

## 概要

本ドキュメントは、FreeBSDシステムにおけるプロセス状態・スワップ・TTY統計レポート(pstat)の帳票設計書である。pstatコマンドはシステムのファイルテーブル、TTYデバイス状態、スワップデバイス使用状況を表示する。swapinfoとして起動した場合はスワップ情報のみを表示する。

### 本帳票の処理概要

**業務上の目的・背景**：システム管理者がカーネル内部のファイルテーブル、TTYデバイスの状態、スワップスペースの使用状況を確認し、リソース枯渇の診断やキャパシティプランニングに活用するためのレポートである。

**帳票の利用シーン**：オープンファイル数の確認、TTYデバイスの接続状況確認、スワップスペースの使用率確認、システムリソースの概要把握。

**主要な出力内容**：
1. ファイルテーブル（-f）：オープンファイル数、ファイルタイプ、フラグ、参照カウント、データポインタ
2. TTYデバイス一覧（-t）：TTYデバイス名、入出力キュー、状態フラグ
3. スワップスペース（-s）：スワップデバイス名、サイズ、使用量、空き容量、使用率
4. 全体サマリー（-T）：ファイル数/上限、スワップ使用量/合計

**帳票の出力タイミング**：コマンド実行で即時出力。

**帳票の利用者**：システム管理者、カーネル開発者。

## 帳票種別

一覧表/集計表（テキスト形式のシステム状態レポート）

## 利用画面

| 画面No | 画面名 | URL/ルーティング | 出力操作 |
|--------|--------|-----------------|---------|
| N/A | ターミナル/コンソール | N/A | `pstat [-Tfghkmnst] [-M core [-N system]]` または `swapinfo [-ghkm] [-M core [-N system]]` コマンド実行 |

## 出力形式

### 基本仕様

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

## 帳票レイアウト

### ファイルテーブル（-f）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | LOC | ファイル構造体ポインタ | xf_file | 16進数 | 8/16桁 |
| 2 | TYPE | ファイルタイプ | xf_type | 文字列("inode","socket"等) | 6桁 |
| 3 | FLG | フラグ(Read/Write/Append/async) | xf_flag | RWAI文字 | 4桁 |
| 4 | CNT | 参照カウント | xf_count | 整数 | 3桁 |
| 5 | MSG | メッセージカウント | xf_msgcount | 整数 | 3桁 |
| 6 | DATA | データポインタ | xf_data | 16進数 | 8/16桁 |
| 7 | OFFSET | オフセット | xf_offset | 16進数 | 16桁 |

### TTYデバイス一覧（-t）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | LINE | デバイス名 | devname(xt_dev) | 文字列 | 10桁 |
| 2 | INQ | 入力キューサイズ | xt_insize | 整数 | 5桁 |
| 3 | CAN | 入力正規化文字数 | xt_incc | 整数 | 4桁 |
| 4 | LIN | 入力行文字数 | xt_inlc | 整数 | 4桁 |
| 5 | LOW | 入力ロー・ウォーターマーク | xt_insize - xt_inlow | 整数 | 4桁 |
| 6 | OUTQ | 出力キューサイズ | xt_outsize | 整数 | 5桁 |
| 7 | USE | 出力使用量 | xt_outcc | 整数 | 4桁 |
| 8 | LOW | 出力ロー・ウォーターマーク | xt_outsize - xt_outlow | 整数 | 4桁 |
| 9 | COL | カラム位置 | xt_column | 整数 | 5桁 |
| 10 | SESS | セッションID | xt_sid | 整数 | 5桁 |
| 11 | PGID | プロセスグループID | xt_pgid | 整数 | 5桁 |
| 12 | STATE | TTY状態フラグ | xt_flags | 文字列 | 可変 |

### スワップデバイス（-s）

| No | 項目名 | 説明 | データ取得元 | 表示形式 | 列幅 |
|----|-------|------|-------------|---------|-----|
| 1 | Device | デバイス名 | ksw_devname / devname(xsw_dev) | 文字列 | 15桁 |
| 2 | Size | 合計サイズ | ksw_total * pagesize | 人間可読/ブロック | 可変 |
| 3 | Used | 使用量 | ksw_used * pagesize | 人間可読/ブロック | 8桁 |
| 4 | Avail | 空き容量 | (total - used) * pagesize | 人間可読/ブロック | 8桁 |
| 5 | Capacity | 使用率 | used * 100.0 / total | パーセント | 5桁 |

## 出力条件

### 抽出条件

| 条件名 | 説明 | 必須 |
|-------|------|-----|
| -f | ファイルテーブル表示 | No（いずれか1つ以上必須） |
| -t | TTYデバイス表示 | No |
| -s | スワップ情報表示 | No |
| -T | サマリー表示 | No |
| swapinfo起動 | argv[0]がswapinfoの場合自動的にスワップモード | 自動 |

### ソート順

特定のソート順なし

### 改ページ条件

改ページ機能なし

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

### 参照テーブル一覧

| テーブル名 | 用途 | 結合条件 |
|-----------|------|---------|
| kern.file (sysctl) | ファイルテーブル | -fオプション |
| kern.maxfiles (sysctl) | 最大ファイル数 | -f/-Tオプション |
| kern.openfiles (sysctl) | オープンファイル数 | -f/-Tオプション |
| kern.ttys (sysctl) | TTYデバイス一覧 | -tオプション |
| vm.swap_info (sysctl) | スワップデバイス情報 | -sオプション |

## 計算仕様

### 計算項目一覧

| 項目名 | 計算式 | 端数処理 | 備考 |
|-------|-------|---------|------|
| スワップサイズ(表示) | nblks * pagesize / blocksize | blocksize依存 | CONVERT(v)マクロ（450行目） |
| スワップ使用率 | used * 100.0 / total | 小数点なし(%5.0f) | |
| human readable | humanize_number() | 小数点1桁 | -hオプション時 |

## 処理フロー

### 出力フロー

```mermaid
flowchart TD
    A[コマンド実行] --> B{argv[0]がswapinfo?}
    B -->|Yes| C[スワップモード固定]
    B -->|No| D[getoptでオプション解析]
    C --> E[スワップ情報表示]
    D --> F{指定オプション判定}
    F -->|f or T| G[filemode: ファイルテーブル]
    F -->|t| H[ttymode: TTY一覧]
    F -->|s or T| I[swapmode: スワップ情報]
    G --> J[終了]
    H --> J
    I --> J
```

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 表示メッセージ | 対処方法 |
|----------|---------|--------------|---------|
| kvm_openfiles失敗 | -M/-Nオプション時 | errx(1, "kvm_openfiles: ...") | コアファイル確認 |
| kvm_nlist失敗 | カーネルシンボル未定義 | warnx("undefined symbol: ...") | カーネルバージョン確認 |
| xtty構造体サイズ不一致 | カーネルバージョン不一致 | errx(1, "struct xtty size mismatch") | カーネル同期 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定データ件数 | ファイル数（数百～数万）、TTY数（数～数十）、スワップ数（1～数個） |
| 目標出力時間 | 即時 |
| 同時出力数上限 | N/A |

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

- ファイルテーブルの参照にはroot権限が必要
- スワップ情報は一般ユーザーでも参照可能（sysctl経由）
- -nオプションでデバイス名の代わりにデバイス番号を表示可能

## 備考

- swapinfoとpstatは同一バイナリで、argv[0]の判定により動作が変わる（115-127行目）
- ファイルヘッダーは32bit/64bitでフォーマットが異なる（210-216行目: fhdr32, fhdr64）
- TTY状態フラグはttystates配列（286-324行目）で文字にマッピング
- -gオプションで1GB単位、-kで1KB単位、-mで1MB単位のブロックサイズ（BLOCKSIZE環境変数設定）

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pstat.c | `usr.sbin/pstat/pstat.c` | 63-82行目: NL_CONSTTY～NL_MARKERのenum定義とnlist配列。カーネルシンボル参照用 |
| 1-2 | pstat.c | `usr.sbin/pstat/pstat.c` | 286-324行目: ttystates配列。TTY状態フラグから文字への変換テーブル |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pstat.c | `usr.sbin/pstat/pstat.c` | 103-201行目: main関数。swapinfo/pstatの動作切り替え、各モードのディスパッチ |

**主要処理フロー**:
1. **115-127行目**: argv[0]からswapinfo/pstat判定
2. **129行目**: getoptでオプション解析
3. **192-199行目**: モード分岐（filemode, ttymode, swapmode）

#### Step 3: 各出力モードを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pstat.c | `usr.sbin/pstat/pstat.c` | 354-412行目: filemode関数。KERN_FILEsysctlでxfile構造体取得、ファイルタイプ別出力 |
| 3-2 | pstat.c | `usr.sbin/pstat/pstat.c` | 276-284行目: ttymode関数。kvm/sysctl切替でxtty構造体取得、ttyprt関数で出力 |
| 3-3 | pstat.c | `usr.sbin/pstat/pstat.c` | 540-597行目: swapmode関数。kvm_getswapinfo/vm.swap_info sysctl |

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

```
main() [103行目]
    |
    +-- kvm_openfiles() ... -M/-Nオプション時
    +-- kvm_nlist() ... カーネルシンボル解決
    +-- filemode() [354行目]
    |      +-- getfiles() [414行目] ... sysctl(KERN_FILE)
    +-- ttymode() [276行目]
    |      +-- ttymode_kvm() [221行目] ... kvmからTTY取得
    |      +-- ttymode_sysctl() [254行目] ... kern.ttys sysctl
    |      +-- ttyprt() [326行目] ... TTY行出力
    +-- swapmode() [590行目]
           +-- swapmode_kvm() [540行目] ... kvm_getswapinfo
           +-- swapmode_sysctl() [555行目] ... vm.swap_info
           +-- print_swap_header() [455行目]
           +-- print_swap() [508行目]
           +-- print_swap_line() [474行目]
           +-- print_swap_total() [521行目]
```

### データフロー図

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

kern.file (sysctl) ────▶ filemode() ... ファイル一覧  ──▶ 標準出力
kern.ttys (sysctl) ────▶ ttymode() ... TTY一覧          (printf)
vm.swap_info (sysctl) ─▶ swapmode() ... スワップ情報
カーネルメモリ (kvm) ───▶ *_kvm() ... コアダンプ時
```

### 関連ファイル一覧

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