閉じる

OSは何をしている?プロセス・メモリ・ファイル管理の要点

アプリが快適に動く裏では、OSがCPUやメモリ、ストレージなどの資源を調整し、プログラムを安全かつ効率的に実行しています。

本記事では、初心者向けにOSの基本役割を、プロセス・メモリ・ファイル管理の観点から分かりやすく解説します。

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

OSは何をしているか

資源の管理と割り当て

OSはコンピュータ資源(CPU、メモリ、ストレージ、ネットワーク、デバイス)を公平かつ効率よく分配します。

複数のプログラムが同時に動いても、各プログラムが互いに邪魔をせず、必要最低限の資源を得られるように調停します。

抽象化と統一インターフェース

OSは複雑なハードウェアを「抽象化」して、開発者に統一的な操作手段を提供します。

例えば、異なるSSDやHDDでも「ファイル」として同じ手順で読み書きできます。

この抽象化により、アプリはハードごとの差異を意識せず作れます。

安全性と隔離

OSはプロセスごとに領域を隔離し、他のプログラムやカーネル領域への不正なアクセスを防ぎます。

アクセス権限や実行モードを使って、誤作動や悪意ある振る舞いからシステムを守ります。

ユーザ空間とカーネル空間

2つの実行モード

一般的なOSは、アプリが動く「ユーザ空間」と、OSの中枢である「カーネル空間」を分けています。

CPUはユーザ(制限)モードと特権(スーパーバイザ)モードを切り替え、危険な操作(生のデバイス制御など)はカーネルのみが実行できます。

空間の隔離とクラッシュ防止

ユーザ空間のアプリがクラッシュしても、カーネル空間や他のアプリに被害が波及しにくい設計になっています。

これによりシステム全体の安定性が保たれます。

俯瞰で見る違い

観点ユーザ空間カーネル空間
権限制限ありフルアクセス
代表例アプリ(ブラウザ、エディタ)OS本体、ドライバ
主な操作計算、表示、システムコール発行メモリ管理、スケジューリング、I/O制御
障害の影響そのプロセスが停止システム全体に影響し再起動が必要になり得る

システムコールの役割

カーネルへの唯一の正規ルート

アプリがファイルI/Oやネットワーク、プロセス生成などを行う際は、システムコールを通じてカーネルに依頼します。

ユーザ空間からカーネル空間へ安全に橋渡しするための仕組みです。

代表的なシステムコール例

システムコール主な用途
open/closeファイルやデバイスを開く/閉じる
read/writeデータの読み込み/書き込み
fork/exec/waitプロセス作成/実行プログラムの置換/終了待ち
mmapファイルや匿名領域をメモリにマップ
socket/connect/acceptネットワーク通信の確立
ioctlデバイス特有の制御

ライブラリ関数との違い

ライブラリ関数はユーザ空間の便利機能で、内部でシステムコールを呼ぶ場合もあります。

例えば、freadは標準Cライブラリのバッファリング付きI/Oで、最終的にreadなどのシステムコールを発行します。

すべてのライブラリ関数がシステムコールを呼ぶわけではありません。

プロセス管理の要点

スケジューラとコンテキストスイッチ

スケジューラの目的

スケジューラはどのプロセス(やスレッド)にCPUをいつどれだけ使わせるかを決めます。

応答性を重視する対話型タスク、スループット重視のバッチ処理、リアルタイム性が必要なタスクなど、目的に合わせて方針(ポリシー)が調整されます。

コンテキストスイッチの流れ

コンテキストスイッチとは、実行中のプロセスのCPU状態(レジスタ、プログラムカウンタなど)を保存し、次に動かすプロセスの状態を復元する処理です。

スイッチにはコストがかかるため、無闇にスレッド数を増やすと逆に遅くなることがあります。

優先度とプリエンプション

多くのOSはプリエンプティブ方式で、優先度の高いタスクが低いタスクの実行を割り込んでCPUを獲得します。

タイムスライス(一定時間枠)を使って公平性を担保しつつ、相対的な優先度で応答性を調整します。

プロセスの生成と終了

生成の基本(概念)

UNIX系では、親プロセスがforkで自身を複製し、execで別プログラムに置き換える流れが一般的です。

WindowsではCreateProcessが一度に新しいプロセスを生成します。

生成時にはメモリ空間やファイルディスクリプタ(ハンドル)の継承などが管理されます。

終了とリソース解放

プロセスが終了するとき、OSは使用中のメモリやファイル、ロックなどのリソースを回収します。

プロセスは終了コード(戻り値)を親に報告し、親は待機(例: wait)して結果を受け取ります。

ゾンビ・孤児プロセス

子プロセスの終了情報を親が回収しないと、最小限の情報だけが残るゾンビプロセスになります。

親が先に終わると孤児になり、OSが引き取り後始末します。

適切な待機やタイムアウト設計が重要です。

プロセス間通信 IPC

パイプとソケット

パイプは同一マシン内のプロセス間で一方向のバイトストリームをやりとりする手段です。

名前付きパイプ(FIFO)は関係のないプロセス間でも使用できます。

ソケットはネットワーク越しも含めて双方向通信を可能にし、クライアント・サーバ型アプリの基礎になります。

共有メモリと同期

共有メモリは最速クラスのIPCですが、レースコンディションを避けるためにミューテックスやセマフォなどの同期原語が必要です。

高速だが難易度が上がるため、設計時の責務分離とテストが重要です。

メッセージキューとシグナル

メッセージキューは順序付きの短いメッセージを送受信する仕組みで、疎結合な設計に向きます。

シグナルは非同期通知に使われ、終了要求やタイマー通知などの簡易な合図に適しています。

メモリ管理の要点

仮想メモリとアドレス空間

仮想アドレスの利点

仮想メモリは、各プロセスに連続して見える専用のアドレス空間を提供します。

これにより、プロセス間の隔離、メモリ不足の緩和(スワップと組み合わせ)や、巨大なデータの部分読み込みなどが可能になります。

アドレス空間のレイアウト(概念)

一般的に、実行コード、静的データ、ヒープ、スタック、共有ライブラリ、カーネルマップ領域などが論理的に配置されます。

詳細はOSやアーキテクチャに依存しますが、このレイアウトが保護や効率の要になります。

メモリマップドファイル

mmapのような機能により、ファイル内容をメモリに直接マップして扱えます。

大きなファイルの一部だけを必要に応じて読み込めるため、I/O効率が高まります。

ページングとメモリ保護

ページとページテーブル

仮想メモリは固定長の単位(ページ)で管理され、仮想ページと物理フレームの対応関係をページテーブルに記録します。

これにより、連続していない物理メモリを連続して見せられます。

TLBと遅延

変換後バッファ(TLB)は仮想→物理の変換結果をキャッシュする仕組みです。

TLBミスは性能低下の一因となるため、メモリアクセスの局所性を高める設計が有効です。

守る仕組み(保護ビット)

ページごとに読み取り・書き込み・実行の可否やユーザ/カーネル権限を設定できます。

これにより、実行不可メモリでのコード実行や、他プロセスのメモリ破壊が防がれます。

メモリ割り当てとスワップ

ヒープ割り当ての裏側

mallocのようなユーザ空間のメモリ割り当ては、内部でより大きなページ単位の確保(mmapやbrkなど)を行い、アプリに小分けで渡します。

断片化を抑えつつ、必要に応じてOSから返却・再確保を行います。

ページキャッシュの存在

OSはディスク上のファイルデータをページキャッシュに保持し、再読み込みを高速化します。

空きメモリは無駄ではなくキャッシュとして有効活用されます。

スワップとスラッシング

物理メモリが足りないと、使われていないページをディスク(スワップ領域)へ退避します。

過剰なスワップはスラッシング(頻繁な入れ替え)を引き起こし、極端な性能低下につながるため、メモリの見積りと監視が大切です。

ファイル管理の要点

ファイルシステムとディレクトリ

階層構造とパス

ファイルシステムは階層的なディレクトリ構造でファイルを管理し、絶対パス(/から開始)と相対パス(現在位置基準)を使い分けます。

これにより整理と探索が容易になります。

メタデータとinode(概念)

ファイルには中身のデータに加えて、サイズ、タイムスタンプ、所有者、パーミッションなどのメタデータがあります。

UNIX系ではinodeがメタデータとデータブロックの位置を管理します。

ジャーナリングと信頼性

突然の電源断でも整合性を保つため、ジャーナリング型ファイルシステムは更新履歴を安全に記録します。

障害後の復旧時間短縮やデータ破損の軽減に寄与します。

所有権とパーミッション

基本のrwxとUGO

UNIX系では所有者(User)、グループ(Group)、その他(Others)ごとに読み取り(r)、書き込み(w)、実行(x)の権限を設定します。

これにより、最小権限での運用が実現します。

対象読み取り(r)書き込み(w)実行(x)
所有者700(所有者のみ全権)
グループ不可750(グループは実行可)
その他不可不可644(公開読み取り)

ACLと拡張属性

より細かな制御が必要な場合、ACLで個別ユーザ・グループに権限を付与できます。

拡張属性では、セキュリティラベルや特殊フラグ(例: 不変属性)を付けて保護を強化します。

実務での考え方

原則は「必要最小限の付与」です。

書き込み可能な範囲を限定し、機密ファイルはグループ単位で絞り、ログや公開ファイルは読み取り専用で配布するなど、役割に応じて分けます。

ファイル入出力とファイルディスクリプタ

ファイルディスクリプタの正体

ファイルディスクリプタ(Windowsではハンドルに相当)は、OSが管理する「開いたファイルやソケットの参照番号」です。

アプリはこの番号を通じてreadやwriteを呼び、OSが実体を操作します。

標準入出力とリダイレクト

プロセス起動時には標準入力(0)、標準出力(1)、標準エラー(2)が用意されます。

シェルのリダイレクトやパイプを使うと、出力先や入力元を別ファイルや別プロセスにつなぎ替えられます。

これがUNIX哲学の「道具の組み合わせ」を支えます。

同期型I/Oと非同期I/O

同期I/Oは完了まで呼び出し元を待たせますが、非同期I/Oは完了通知やイベント駆動で待ちを減らします。

高負荷のネットワークサーバでは非同期I/Oやイベントループを採用することで、スレッド数やコンテキストスイッチの増大を抑えられます。

まとめ

OSは、資源の管理、抽象化の提供、安全な隔離という3本柱で、アプリを安定かつ効率的に動かす土台を作っています。

プロセス管理ではスケジューラとコンテキストスイッチが公平性と応答性を担保し、生成・終了やIPCが多様な連携を可能にします。

メモリ管理では仮想メモリとページングが安全性と柔軟性を提供し、ページキャッシュやスワップが性能と容量をバランスします。

ファイル管理では、ファイルシステムの階層構造、パーミッションとACL、ファイルディスクリプタによる統一I/Oが、扱いやすさと安全性を両立します。

これらの要点を押さえることで、プログラムの振る舞いを理解し、より堅牢で効率的なソフトウェア設計へと近づけます。

この記事を書いた人
エーテリア編集部
エーテリア編集部

このサイトでは、プログラミングをこれから学びたい初心者の方に向けて記事を書いています。 基本的な用語や環境構築の手順から、実際に手を動かして学べるサンプルコードまで、わかりやすく整理することを心がけています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!