Kernel:プログラムとプロセス(日経Linux 2003.10要点まとめ)

マルチユーザ・マルチタスクのシステムではプロセス管理が非常に重要

  • プログラム単位ではなくプロセス単位で実行が管理される/プロセスIDの使用
    • 同時に同じプログラムを2種類動作させてもお互いが干渉しない
  • Linuxではメモリー領域を仮想メモリー空間を割り当てる方式で干渉を防止している
    • 物理メモリーを"ページ"というブロック単位で管理する
    • 複数のページの集合が仮想メモリ
    • 各プロセスごとに仮想メモリーを割り当て、Kernelが物理メモリーとの紐付けを管理する
      • 仮想メモリーと物理メモリーを紐付けるために変換によるパフォーマンス低下が発生するが、アドレス変換のキャッシュ機構を搭載するなどの工夫がされている

プロセスの生成から終了までの流れは以下の通り。

  1. プロセスがfork()システム・コールを発行して自分自身を新しいプログラムに置き換える(複製)
  2. 複製されたプロセスはexec()システム・コールを発行して自分自身を新しいプログラムに置き換える(処理)
  3. 処理完了後にexit()システム・コールにより自分自身を終了させる

※親プロセスは子プロセスが終了するのを待機する

各項目の詳細は以下の通り。

fork()システム・コール

  • 呼び出し元プロセスの複製プロセスを生成するシステム・コール
  • 親プロセスのプロセスID以外の全ての情報がコピーされる(メモリー内容、ファイル情報、命令位置など)
  • プロセスが複製されることにより環境変数やプロセス間通信機能が簡単に使用できるというメリットがある
  • 親プロセスはfork()システム・コールの戻り値として子プロセスのプロセスIDを記録する(親子関係の明確化)

exec()システム・コール

  • 自分自身を新しいプログラムに置き換えて実行するシステム・コール
  • 仮想メモリー空間を一度開放し、新たに作成してそこに指定したプログラムを割り当てて実行する

※メモリー空間以外の全ての情報はそのまま引き継ぐ

※全てのプロセスは親子関係を持つ。ただし、全てのプロセスの根幹になっているinitプロセス(プロセスID:1)だけはKernelが自身で生成する。全てのプロセスはinitを基幹とするツリー構造で構成される。

exit()システム・コール

  • カーネルにより対象プロセスが使用していた資源を解放する

※プロセス自体の管理情報は親プロセスによって削除される

wait()システム・コール

  • 子プロセスが終了された時点で子プロセスの管理情報を削除するシステム・コール
  • 発行のタイミングは子プロセスをfork()してすぐでも終了シグナルを受け取った時点でもかまわない

※親プロセスによってwait()が発行されていない終了プロセスを"defunctプロセス"もしくは"ゾンビプロセス"と呼ぶ
※wait()は必ずしも直接の親プロセスが発行する必要はない(initが対象の子プロセスを引き継ぐ)
プロセスは直接お互いに情報を交換することは出来ないが、Kernelを通じて情報の交換を行うことができる=プロセス間通信(IPC / Inter Process Communication)

  • IPCの最も基本的なものとして"シグナル"がある
    • 稼働中のプロセスに対してシグナルを送信することによりあらかじめ決めた振る舞いをさせることができる

Linuxが標準で利用できるシグナルの例

シグナル名 標準動作 通知内容
SIGHUP プロセス終了 端末のハングアップ検出
SIGINT プロセス終了 端末からの割り込み
SIGQUIT コア・ダンプして終了 コア・ダンプ終了要求
SIGTERM プロセス終了 プロセスの終了要求
SIGKILL プロセス終了 プロセスの強制終了要求
SIGSTOP プロセスの実行中断 プロセスの実行中断要求
SIGSEGV コア・ダンプして終了 不正アドレスへのアクセス
SIGCONT 無視 or 実行再開 中断状態のプロセス再開
SIGUSR1 プロセス終了 ユーザー定義のシグナル

※シグナルを受けた際の振る舞いはKernelに登録することにより変更できる=登録情報:シグナル・ハンドラ

kill()システム・コール

  • プロセスが他のプロセスに対してシグナルを送る場合に使用するシステム・コール

※元々プロセスを終了させる仕組みだったためにkillという名称になっているが、現在ではシグナルは色々な用途に用いられる
※シグナルで送信できるのはシグナル番号のみ