Linuxプロセスの基礎概念とメモリ管理

オペレーティングシステムの役割

オペレーティングシステム(OS)はハードウェアとアプリケーションの間で動作する基盤ソフトウェアです。主な機能は以下の通り:

  • ハードウェアドライバを通じて物理デバイスを管理
  • システムコールを介してアプリケーションにサービスを提供
  • リソースの効率的な配分と保護を実現

システムコールとライブラリ関数

システムコールはカーネルと直接通信する低レベルインターフェースです。例えばファイル読み込みでは:

#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);

この関数はカーネル内でsys_read()を実行します。アプリケーション開発者は通常、fread()のような高レベルのC標準ライブラリ関数を使用します。ライブラリ関数はシステムコールをラップし、開発者の利便性を向上させます。

プロセスの実体構造

実行中のプログラムはプロセスとして管理されます。Linuxではtask_struct構造体がプロセスのすべての情報を保持します。

プロセス状態の詳細

状態コード意味特徴
R実行可能状態CPU実行待ちまたは実行中(R+はフォアグラウンド実行)
Sインタラプティブル待機イベント待ち(キーボード入力など)
Dアンインタラプティブル待機I/O操作中(信号で中断不可)
T停止状態デバッガによる一時停止など
Zゾンビ状態終了した子プロセスの残骸(親プロセスが回収待ち)

ゾンビプロセスの発生メカニズム

子プロセスが終了後、親プロセスがwait()システムコールを呼び出さないとゾンビ状態が発生します。initプロセス(PID=1)は孤児プロセスを回収する役割を持ちます:

while (1) {
    pid_t child = waitpid(-1, &status, WNOHANG);
    if (child > 0) cleanup_zombie(child);
}

仮想アドレス空間の仕組み

各プロセスは独立した仮想メモリ空間を持ち、物理メモリへのマッピングはページテーブルで管理されます。

コピー・オン・ライトの実装

fork()実行時のメモリ最適化例:

int main() {
    int value = 100;
    pid_t pid = fork();
    
    if (pid == 0) {  // 子プロセス
        value = 200;  // 書き込み時にメモリ領域を分離
        printf("Child: %d\n", value);
    } else {  // 親プロセス
        sleep(1);
        printf("Parent: %d\n", value);
    }
    return 0;
}

実行結果:

Child: 200
Parent: 100

この動作はコピー・オン・ライト(COW)と呼ばれ、メモリ使用量を最適化します。

環境変数の管理

環境変数はプロセスの実行環境を設定する文字列の集合です。主な用途:

  • PATH: 実行可能ファイルの検索パス
  • HOME: ユーザーディレクトリのパス
  • SHELL: 使用シェルのパス

カスタムコマンドをPATHに追加する方法:

export PATH="$PATH:/home/user/bin"

この設定はセッション終了時にリセットされます。永続化する場合は~/.bashrcに記述します。

環境変数の取得方法

C言語でのアクセス例:

#include <stdlib.h>
int main(int argc, char *argv[], char *envp[]) {
    for (int i = 0; envp[i]; i++) {
        printf("%s\n", envp[i]);
    }
    return 0;
}

タグ: Linuxカーネル プロセス管理 仮想メモリ

7月22日 17:13 投稿