【OS入門#1】Operating Systemを学習:OSって何?
はじめに
OSって、なんとなく難しそうで敬遠しがち。だけど、プログラミングを続けているといつか必ずぶつかる「謎の黒幕」でもあります。
なぜメモリが管理されるのか?なぜプロセスがスケジューリングされるのか?──そのひとつひとつに、考え抜かれた思想と歴史があります。
この記事では、「なんとなく動いてる」から脱却し、OSというシステムを根から理解していくための学びを共有します。
Operating Systemとは何か
OSのあの恐竜本には以下のように書かれている。
“An operating system is software that manages a computer’s hardware. It also provides a basis for application programs and acts as an intermediary between the computer user and the computer hardware.”
osとはハードウェアを管理するソフトウェアのことである。アプリケーションプログラムの基盤であり、ユーザーとハードウェアの仲介者としての役割として機能する。osの驚異的な一面として、とても広く様々であるコンピュータの環境においてタスクを遂げるためにどのように動作するかというものが挙げられる。
OSは実際に何をしているのか
まずはosが何をしているかを知るためにコンピュータシステム全体から見ていく。コンピュータシステムには大まかにハードウェア、オペレーティグシステム、アプリケーションプログラム、そしてユーザーがある。
ハードウェアにはCPUやメモリ、I/Oデバイスなどがあり、これらは主にコンピュータのベースとなるものである。アプリケーションプログラムでは、ワードプロセスやスプレッドシート、コンパイラ、Webブラウザなどが挙げられる。そしてオペレーティングシステムではハードウェアを制御し、様々なアプリケーションプログラムを用いて多様なユーザーのためにハードウェアの使用を采配する。
まとめると、役割は主に三つであり、
-
資源管理(Resource Management)
CPU・メモリ・ディスク・I/O など限られた資源を、効率よく配分する。 -
仲介(Abstraction / Interface)
アプリケーションが直接ハードを操作するのは危険・不便なので、**安全な抽象化された操作手段(API、システムコールなど)**を提供。 -
制御と保護(Control & Protection)
各ユーザー・プロセスが、互いに干渉せず正しく動作するように制御する。
これらを以下にて解説していく。
資源管理(Resource Management)
-
CPU:プロセススケジューリング
ラウンドロビンや優先度ベースなどのアルゴリズム、割り込み処理(interrupt)でプロセスを切り替えて複数のプロセスの順番や使用時間を管理する。 -
メモリ:動的メモリ割当と解放
他のプロセスへの不正なアクセスの防止するためのメモリ保護やページング、セグメンテーションによってプロセスに割り当てるRAMの範囲を管理する。 -
ストレージ(ディスク)とファイルシステム
FAT, ext4, NTFSOperating.System.Concep…などの例があり、ファイルの作成や読み書き、削除などのファイルシステムとディスクブロックの割り当てと管理。 -
I/Oデバイス
プリンタのバッファ制御のような非同期的な入出力の制御や、デバイスドライバと連携して制御する。
保護とセキュリティ(Protection & Security)
Operating Systemの恐竜本には以下のように書いてある。
”Protection is any mechanism for controlling the access of processes or >users to the resources defined by a computer system.”
つまり、誰が・何を・どう使えるかを制御するということであり、セキュリティと違う点として、「悪意」ではなく「誤操作」も含めて制御対象になる。
例えば、CPUやメモリに対しての保護とセキュリティは、他のプロセスの暴走や乗っ取りを防ぐことであり、ファイル・ディスクに対しては秘密データへのアクセス制限、デバイスで言うとカメラやネットワークの悪用防止である。
また、直接I/Oポートやメモリにアクセスさせないなどといった、ユーザープログラムとカーネル空間を明確に分離するカプセル化と境界保護として**Ring Protection(特権レベル)**を採用している。CPUには 特権レベル(Ring 0〜Ring 3) という概念がり、Userモード(普通のアプリケーションなど)は特権レベル3(Ring3)であり、kernelモード(OSの内部、ハード制御)は特権レベル0(Ring0)となっている。普段アプリがOSを操作するには、system callという門を通る。
APIの位置付け(Application Programming Interface)
恐竜本では以下のように説明がなされている。
”An API specifies a set of functions that an application can invoke to obtain services from the operating system.”
つまり、アプリがOSの機能を使うための入り口がAPIである。OSの内部構造を知らなくても、ファイル操作・メモリ確保・プロセス生成などができる。
アプリがAPI関数を呼び出し、システムコールを呼び出し、そしてOSカーネルに命令を出す。例えば、UNIX系では以下のコマンドがある。:
// アプリが呼ぶAPI関数
int fd = open("hello.txt", O_RDONLY);
// 実際には内部で「システムコール open()」を使ってOSに依頼している
この「open」は、glibcなどの標準ライブラリに実装されたラッパー関数であり、中で syscall()
を呼んで、カーネルモードに切り替えて処理している。
kernel trap(トラップ命令)
kernel trapとは、先ほどのRing protectionにあったように、OS(カーネル)は特権モード(Ring 0)で動いてる。
しかしながらアプリはUserモード(Ring 3)で動いており、直接ハードウェアや重要な処理にアクセスできないので、一時的にカーネルに「お願いしに行く」ための専用通路=カーネルトラップが必要となる。
つまり、User空間 → kernel空間 に移るには、CPUのモードを切り替える必要があり、その際に必要な命令をトラップ命令と呼び、kernel trapとは、ユーザープログラムからカーネルに制御を渡すための特別な仕組みである。
kernel torapやdeamon、libralyもAPIの一部である。
OSが提供するサービスモデル
ユーザーやアプリにとってのOSとは、ただの機能の集合体というわけではなく、どう提供されるかというサービスモデルもOS設計の一部である。
-
command
代表的なものに、shell(zsh, bash, shなど)があり、ユーザーが命令を一つずつ入力して実行する形式である。各コマンドが独立したプロセスであり、標準入力/出力を繋いでいる。 -
deamon
deamon(デーモン)は、普通のアプリケーションとは違い、ユーザーが明示的に起動せず、常にバックグラウンドで待機しているものである。UNIX哲学に"Everything is a file / service"というものがある。OSは必要な機能を小さな常駐プログラム(デーモン)として分けられており、init/systemdが起動時に全部のデーモンを起動して、OS全体が動くようになる。 -
クライアント/サーバーモデル
あるプロセス(サーバ)がリクエストを待ち、別のプロセス(クライアント)がそれを呼び出すモデルであり、例えばWebブラウザとWebサーバに使用されている、ソケット通信(socket()
/bind()
/listen()
/accept()
)などである。 -
Batch(バッチ処理)
人が関わらず、あらかじめ用意された命令列をまとめて処理する方式であり、これは初期のOS(1950〜60年代)ではパンチカードを読み込んで一括処理していたのと同様である。
今でも、shellスクリプトや Cのmake、CIツール(GitHub Actionsなど)はバッチ処理の発展形と言える。 -
TSS(Time Sharing System)
複数のユーザーが1台のコンピュータを同時に使う仕組みであり、プロセスを高速に切り替えて、まるで複数人が同時に使っているかのように見せることができる。
リアルタイム制御(Real-Time Control)
リアルタイム制御は、正確なタイミングで正確な動作を保証するという非常にシビアなOSの役割である。そもそもリアルタイム制御とは:
“A real-time system is used when rigid time requirements have been placed on the operation of a processor or the flow of data.”
つまり、処理の「正確さ」だけでなく「タイミング」も重要であることがわかる。
-
transaction(トランザクション)
元々はDB用語であり、複数の処理をまとめて不可分な単位として扱う概念である。リアルタイムでは「一連の処理の原子性・一貫性・完了性の確保」が必要である。
プログラムにおいて、センサ読み取り→判断→制御信号発行という順番のはずが、途中で止まったり、並列実行されて矛盾が起きては困る。そこでトランザクションを用いることでデータの整合性を保つことができる。 -
Synchronization(同期)
複数のプロセスやスレッドが協調して安全にデータ共有するための制御技術である。代表例には、semaphore(セマフォ)やmutex(ミューテックス)、monitor(モニタ)などがある。 -
Scheduling(スケジューリング)
「どのプロセスをいつ実行するか」を決めることであり、
リアルタイムOSでは、FIFOや優先度付きスケジューリング、 RMS(Rate Monotonic Scheduling)、EDF(Earliest Deadline First)などといったアルゴリズムが使用されている。
UNIXのBootstrapping(ブートストラップ)
“The procedure of starting a computer by loading the kernel is known as booting the system.”
つまり、電源ONからOSが立ち上がるまでの一連の流れを指す。
まず、電源を入れると、OSがすぐに立ち上がるのではなく、BIOS/UEFIがブートローダーをロードする。GRUB(ブートローダー)が選んだカーネル(vmlinuz)と初期RAMディスク(initramfs)を読み込み、CPUをカーネルモードにして、initプロセスを起動する。
BIOS/UEFI → Bootloader → カーネル → init/systemd → ログイン
という流れである。
おわりに
リソースの管理、プロセスの切り替え——OSにはまだまだ奥深い役割があります。
例えば、保存されたファイルがいつでも正しく取り出せるのは、なぜなのでしょうか?
次回は、その仕組みを担う「ファイルシステム」に焦点を当てていきます。
参考文献
- Abraham Silberschatz, Peter B. Galvin, Greg Gagne, Operating System Concepts, 10th Edition, Wiley, 2018.: https://amzn.to/44zHODM
Discussion