# 機能設計書 82-プロセス管理コマンド

## 概要

本ドキュメントは、FreeBSDにおけるプロセス管理コマンド群（ps、kill、pkill、pwait）の機能設計を記述する。これらはプロセスの一覧表示・シグナル送信・プロセス待機を行うユーザ空間コマンドであり、FreeBSDベースシステムの基本ユーティリティである。

### 本機能の処理概要

**業務上の目的・背景**：プロセス管理コマンドはシステム運用・障害対応に不可欠なツールである。実行中プロセスの状態確認、不正プロセスの停止、プロセス完了の待機など、システム管理者や開発者がプロセスライフサイクルを管理するための基盤的なインタフェースを提供する。

**機能の利用シーン**：プロセス一覧の確認（ps）、ハングアップしたプロセスへのシグナル送信（kill）、名前パターンによるプロセス検索・停止（pkill/pgrep）、特定プロセスの終了待機（pwait）。シェルスクリプトにおけるプロセス制御にも広く使用される。

**主要な処理内容**：
1. ps: kvm_getprocs()またはsysctl(KERN_PROC)によるプロセス情報取得、フォーマット指定(-o)による柔軟な出力、libxoによるJSON/XML対応出力
2. kill: プロセスIDまたはジョブIDへのシグナル送信。シェルビルトインとしても使用可能（SHELL定義時）
3. pkill/pgrep: プロセス名パターンマッチによるプロセス検索・シグナル送信
4. pwait: 指定プロセスの終了を待機

**関連システム・外部連携**：libkvm（カーネル仮想メモリアクセス）、libxo（構造化出力）、sysctl(3)インタフェース、kinfo_proc構造体。

**権限による制御**：psは一般ユーザで実行可能だが、他ユーザのプロセス表示にはsecurity.bsd.see_other_uids sysctlの設定に依存。killは対象プロセスの所有者またはroot権限が必要。

## 関連画面

該当なし（CLIコマンドのため画面は存在しない）

## 機能種別

プロセス情報照会 / シグナル送信 / プロセス待機

## 入力仕様

### 入力パラメータ

#### ps

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -a | flag | No | 端末に関連するすべてのプロセスを表示 | - |
| -u | flag | No | ユーザ指向フォーマットで表示 | - |
| -x | flag | No | 端末を持たないプロセスも表示 | - |
| -e | flag | No | 環境変数も表示 | - |
| -f | flag | No | フルフォーマット表示 | - |
| -o format | string | No | 出力フォーマット指定（keyword=header形式） | 有効なキーワードであること |
| -p pid | integer | No | 指定PIDのプロセスのみ表示 | 有効なPID |
| -U user | string | No | 指定ユーザのプロセスのみ表示 | 有効なユーザ名/UID |

#### kill

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| -signal | string/int | No | 送信シグナル（デフォルト: SIGTERM） | 有効なシグナル名/番号 |
| pid | integer | Yes | 対象プロセスID | 有効なPID |
| -l | flag | No | シグナル名一覧表示 | - |

### 入力データソース

カーネルのプロセステーブル（sysctl KERN_PROCまたはkvm経由）。コマンドライン引数で指定されたPID・ユーザ名。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| PID | integer | プロセスID |
| TT | string | 制御端末 |
| STAT | string | プロセス状態コード |
| TIME | string | CPU使用時間 |
| COMMAND | string | 実行コマンド名/引数 |
| %CPU | float | CPU使用率 |
| %MEM | float | メモリ使用率 |
| RSS | integer | 物理メモリ使用量 |
| VSZ | integer | 仮想メモリサイズ |

### 出力先

標準出力。libxo対応によりJSON/XML形式での出力も可能。

## 処理フロー

### 処理シーケンス（ps）

```
1. コマンドライン引数解析
   └─ getopt()によるオプション解析、出力フォーマット構築
2. プロセス情報取得
   └─ kvm_openfiles() -> kvm_getprocs()でカーネルからプロセス一覧取得
3. フォーマット設定
   └─ キーワード解決・カラム幅計算
4. ソート処理
   └─ 指定キーでプロセスリストをソート
5. 出力処理
   └─ xo_emit()による構造化出力（テキスト/JSON/XML）
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[コマンドライン引数解析]
    B --> C[kvm_openfiles]
    C --> D[kvm_getprocs: プロセス一覧取得]
    D --> E[出力フォーマット構築]
    E --> F{ソート指定あり?}
    F -->|Yes| G[プロセスリストソート]
    F -->|No| H[出力処理]
    G --> H
    H --> I[xo_emit: 各プロセス情報出力]
    I --> J[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-82-01 | killデフォルトシグナル | シグナル未指定時はSIGTERM(15)を送信 | kill実行時 |
| BR-82-02 | kill -l出力 | シグナル番号を引数として渡すとシグナル名を出力（番号>=128の場合は-128して解釈） | -lオプション指定時 |
| BR-82-03 | psデフォルト表示 | オプション未指定時は現在の端末に関連する自ユーザのプロセスのみ表示 | ps引数なし実行時 |
| BR-82-04 | シェルビルトイン | kill.cはSHELLマクロ定義時にmainがkillcmdにリネームされシェルビルトインとして動作 | bin/sh内ビルトイン時 |

### 計算ロジック

psの%CPU計算はカーネルから取得したプロセスのCPU使用時間をシステム稼働時間で割って算出。ki_pcpuフィールドにdouble型で格納される。

## データベース操作仕様

該当なし（カーネルのプロセステーブルを参照するのみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 権限エラー | kill: 対象プロセスへのシグナル送信権限なし | EPERM エラーメッセージ出力 |
| 1 | プロセス不存在 | kill: 指定PIDのプロセスが存在しない | ESRCH エラーメッセージ出力 |
| 1 | 無効シグナル | kill: 存在しないシグナル名/番号の指定 | nosig()でエラー出力 |
| 1 | kvm初期化失敗 | ps: kvm_openfiles()失敗 | エラーメッセージ出力後終了 |

### リトライ仕様

リトライは行わない。

## トランザクション仕様

該当なし（読み取り専用またはシグナル送信のみ）

## パフォーマンス要件

- psは大量プロセス環境でもsysctl単一呼び出しで全プロセス情報を取得可能
- kvm_getprocs()はカーネルメモリの直接参照により高速なプロセス情報取得を実現

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

- psは他ユーザのプロセス情報を表示可能（security.bsd.see_other_uids sysctlで制御）
- killは対象プロセスの所有者チェックをカーネルが実施（kill(2)システムコール）
- jail環境ではjail内プロセスのみ表示・操作可能

## 備考

- psはlibxoによりJSON/XML/テキスト形式の出力を統一的にサポート
- kill.cは#ifdef SHELLにより/bin/shのビルトインコマンドとしても利用される（kill.c:44-46行目）
- pkill/pgrepは同一バイナリでargv[0]により動作を切り替える

---

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

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

### 推奨読解順序

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

psコマンドのカーネルインタフェースとなるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ps.h | `bin/ps/ps.h` | KINFO構造体（kinfo_procラッパー）、VAR構造体（出力キーワード定義）、VARENT構造体（出力項目エントリ） |

**読解のコツ**: `KINFO`構造体（43-55行目）はカーネルのkinfo_procに追加情報（ki_pcpu, ki_memsize）を付加したラッパー。`VAR`構造体（71-98行目）は出力フォーマットのキーワード定義で、oproc関数ポインタにより各フィールドの出力関数を指定する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ps.c | `bin/ps/ps.c` | main()関数。オプション解析、kvm初期化、プロセス一覧取得、ソート、出力 |

**主要処理フロー**:
1. **71行目**: _PATH_PTS="/dev/pts/"定義
2. **73-74行目**: リスト区切り文字定義（W_SEP=" \t", T_SEP=","）
3. **80行目**: isdigitch()マクロ（安全なisdigit()ラッパー）

#### Step 3: シグナル送信処理（kill）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | kill.c | `bin/kill/kill.c` | main()関数。シグナル解析、PID解析、kill(2)システムコール呼出 |

**主要処理フロー**:
- **44-46行目**: #ifdef SHELLによるシェルビルトイン対応（mainをkillcmdにリネーム）
- **65行目**: デフォルトシグナル SIGTERM
- **68行目**: -lオプション判定（シグナル一覧表示）
- **75-80行目**: シグナル番号の解析（128以上は-128して解釈）

#### Step 4: 出力フォーマット処理（ps）

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | keyword.c | `bin/ps/keyword.c` | 出力キーワードテーブル定義。利用可能な全キーワードとそのVAR構造体 |
| 4-2 | print.c | `bin/ps/print.c` | 各キーワードの出力関数実装 |
| 4-3 | fmt.c | `bin/ps/fmt.c` | 出力フォーマット文字列の解析 |

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

```
ps main()
    |
    +-- getopt()                    # オプション解析
    +-- kvm_openfiles()             # KVMハンドル取得
    +-- kvm_getprocs()              # プロセス一覧取得
    |       +-- sysctl(KERN_PROC)   # カーネル問い合わせ
    |
    +-- parsefmt() / showkey()      # フォーマット解析
    +-- qsort()                     # プロセスソート
    +-- xo_emit()                   # 各プロセス出力
    |       +-- oproc()             # キーワード別出力関数
    +-- kvm_close()                 # クリーンアップ

kill main()
    |
    +-- str2sig() / strtol()        # シグナル解析
    +-- kill(2)                     # シグナル送信システムコール
```

### データフロー図

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

カーネルプロセステーブル ──> ps: kvm_getprocs() ──> プロセス一覧（標準出力）
                             フォーマット処理         JSON/XML/テキスト
                             ソート処理

PID + シグナル ──> kill: kill(2)システムコール ──> シグナル送信
                   シグナル名解決                   （戻り値で成否判定）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ps.c | `bin/ps/ps.c` | ソース | psメインプログラム |
| ps.h | `bin/ps/ps.h` | ヘッダ | psデータ構造定義 |
| extern.h | `bin/ps/extern.h` | ヘッダ | ps外部関数宣言 |
| keyword.c | `bin/ps/keyword.c` | ソース | 出力キーワードテーブル |
| print.c | `bin/ps/print.c` | ソース | キーワード出力関数群 |
| fmt.c | `bin/ps/fmt.c` | ソース | フォーマット解析 |
| nlist.c | `bin/ps/nlist.c` | ソース | カーネルシンボルテーブル参照 |
| kill.c | `bin/kill/kill.c` | ソース | killコマンド/シェルビルトイン |
| pkill.c | `usr.bin/pkill/pkill.c` | ソース | pkill/pgrepコマンド |
| pwait.c | `usr.bin/pwait/pwait.c` | ソース | pwaitコマンド |
