LinuxというのがOSのカーネル(核)であることは前項でお伝えしたとおりですが、では実際に動いているLinuxサーバの構成を見てみましょう。なお、この章はコンピュータの基本的な構成の知識がないと多少難しい内容になっています。可能な限り補足しながら簡潔に説明していきますが、不明点は適宜、別途Web検索などで調べながら読んでいってください。また、「なんでもいいからとりあえずLinux触ってみたい!」「難しいことはともかくLinuxに慣れたい!」という人は序2-5に進んでも構いません。実際のところここからの内容はわかってなくてもLinuxを触ることはできますが、ここを理解しているか否かでLinuxスキルは大きく変わってきます。
まず以下に、LinuxのOSアーキテクチャについて概略図を図示します。
応用ソフトウェアとは様々な機能を提供するソフトウェアで、例えば日常的に利用するインターネットブラウザなどは応用ソフトウェアで、ユーザーランド(ユーザー空間)で動作します。
GUI環境を提供する機能(LinuxではX Window Systemといいます)や、CUIでユーザーからのコマンドを受け付ける機能(シェル)も応用ソフトウェアです。
ユーザーランドはOSの中で、カーネル以外の部分を指し一般ユーザーが操作できる領域となっています。
それに対し、コンピューターが動作するために必要となるソフトウェアを基本ソフトウェアと呼び、これがカーネルになります。
カーネルはOSのソフトウェアとハードウェアの橋渡しを行い、キーボードやマウスなどの入力を受け付け、ソフトウェアに渡すなど、ハードウェアが異なっていてもソフトウェアが動作できるようにします。具体的には、
アプリケーションに割り当てるCPUのリソースはどれくらい?
HDDのどこにデータを保存する?
ハードウェア処理をどのような順番で行う?
などを定義した基本環境を提供してくれています。
ここでちょっとメモリなどのハードウェアの話をしておきましょう。ITの学習を始めると「メモリは机の広さのようなもので〜」なんて例えがよく出てきます。月並みですが、これに沿っていくと各ハードウェアは以下のような役割になります。
コンピュータの5大装置は
演算装置:CPUが担当し、データ処理を行う
制御装置:CPUが担当し、プログラムの解釈や実行、他の装置の制御を行う
記憶装置:主記憶はRAM、補助記憶はHDDが担当し、データの一時的・永続的な保管を行う
入力装置:マウスやキーボードなどが担当し、コンピュータを人間の手で操作するために必要
出力装置:ディスプレイやスピーカーなど担当し、内部のデータを表現するために必要
ですが、このうち、演算・制御・記憶についてが上図の例えにあたります。
当たり前ですが、「頭がいい人が広いデスクで作業すれば成果物を高速で生み出すことができて、引き出しが大きければそれをたくさん溜め込んでおくことができる」わけです。
とはいえですが、いくら頭が良くても作業の手順や段取りがしっちゃかめっちゃかだと期待する成果は出せなくなります。同時に出来そうな仕事とかを別々にやったり、同じ道具を使う仕事なら連続でこなした方が効率がいいのにバラバラに作業してしまったり。
カーネルは、机の上に並んだたくさんの応用ソフトウェアの処理を、最適な順番で処理できるように並べてくれたり、2つ以上を並行して処理するならCPUのリソース分配を決めてくれます(ソフトウェアAは30%の力で、ソフトウェアBは70%の力で処理など)。その他、ストレージ(メモリ)にデータを保存したり読み込んだりしながら、デバイスの入力受付、デバイスの出力受付もカーネルがやってくれます。
このように、カーネルはOSが動くために重要な最低限の機能を提供してくれます。カーネルはハードウェアへ直接アクセスすることができ、コンピュータ内での強い権限を持ちます。このカーネルの動作モードを「特権モード」と呼びます(カーネルモードとも言います)。通常のOSユーザーは「非特権モード(ユーザーモード)」での操作しか出来ないため、ハードウェアに直接触れることは出来ません。全てのプログラムがハードウェアを直接いじくり回せてしまったら、他のプログラムに影響を与えたりエラーや故障の原因になってしまいます。
このため、ユーザーが起動したソフトウェアやプログラムがハードウェアの操作などマシンシステムに影響を与える操作を行いたい場合にはカーネルに対して処理を依頼します。この依頼を「システムコール」と呼びます。
例えば住民票を更新したかったとして、役所に収められている書類を住民が役所に侵入して直接書き換えることが出来てしまったら大問題です。職員でもない普通の人なので、間違えて他の重要書類に手を付けてしまう可能性もあります。その結果、行政処理が滞ったりしてしまうかもしれません。なので基本的には窓口(入力装置)で変更された項目を入力して、裏で事務処理をしている人(CPU)に書き換えをやってもらうわけですが、それと同様です。この仕組みが、サーバマシンの安全性を高めてくれています。
さて、カーネルとハードウェアの関わりがわかったところで実際のカーネルの仕事を具体的に見ていきますが、まずその前に「プロセス」についての説明も必要なので併せて行いましょう。
前項で机の上に並べられた様々なソフトウェアがありましたが、あれがプロセスにあたります。絵で見ると謎のボックスですが、実際にコンピュータの内部で動いているプログラムは目には見えないものなので「プログラムが動いている」状態を便宜的にあのような形にしています。
なにかコマンドをCUI上で実行したとしたら、そのコマンドのプログラムが動作し始めます(補足ですが、LinuxのコマンドはC言語などで記述されたプログラムです)。この時、実際の動きとしては、
コマンドが入力装置で入力されEnterキーが押される
↓
カーネルがコマンドプログラムの情報をCPUに伝える
↓
CPUはプログラムの内容を解釈し演算処理を行う
これがプロセスの生成です。そして、プログラムの終了に伴いプロセスは破棄されます。プロセスにはプロセスID(PID)が割り当てられ、管理されます。先程の役所の例で言えば、事務処理をしてくれる人が書き換えを始めたらプロセス生成、書き換えが終わって新しい住民票を住民に渡したらプロセス終了です。
(ちなみにWindowsではプロセスはサービスと呼ばれます。)
なお、Linuxでは通常プロセスは親プロセスからコピーされて生成されます。これをforkと言います。
Linuxで実行されるコマンドのプロセスは通常はforkされたシェルの子プロセスとして生まれ、子プロセスはexecで指定されたコマンドのプログラムで自身を上書きします。子プロセスはコマンドの実行を終えると親プロセスに終了を伝えて消滅、親プロセス(シェル)は子プロセスの終了を受け取り、ユーザーの次のコマンド入力に備えます。
forkされたプロセスは親プロセスと同じメモリ空間や、開いているファイルなどが共有されます(コピーなので)。ややこしいですが、メモリの確保目的や並列処理をする際に便利だったりプロセス管理目的で有用だったりします。
このプロセスの理解を前提に、カーネルの仕事を見ていきましょう。
プロセスを最適な順番で実行させます(机上のプロセスを処理する順番をどうするか)。スケジューリング方針に従い、優先度とタイムスライスを実行待機しているプロセスごとに割り振り、実行スケジュールを設定していきます。
プロセスごとに割り当てるメモリサイズを決定します(プロセスを実行するために机のスペースをどれだけ使うか)。実際のLinuxカーネルでは仮想メモリを用います。プロセスごとに個別に仮想メモリ空間を与え、実際の物理メモリの容量以上のメモリを持つように振る舞います。仮想メモリはプロセスごとに独立しているため、あるプロセスが他のプロセスに影響を与えることはありません。なお、後述するスワップの利用も含めてメモリ管理はされていますが、カーネルがどんなに頑張ってもメモリ不足に陥ることはあります。
スワッピングという手法を使うことで、物理メモリの容量を超えたプログラムを動作させることが可能です。HDDやSSDなどのストレージに「スワップ領域」と呼ばれる領域を確保しておき、この領域をメインメモリのように扱います。引き出しを無理やりデスクの一部として使って机を広くしているようなものです。
例えば、RAMが4GBしかない場合に3GBのメモリが必要なプログラムを2つ動かそうとすればメモリ不足で動作しません。このとき、例えばスワップ領域を6GB用意しておけば最大10GB使えるので、この2つのプログラムを同時に動作させることができます。LinuxOSをインストールするときに、最初からこのスワップ領域をHDD上に確保しておくことが多いです。
ストレージ上に保存されているデータにアクセスするための方法を提供しています(データを取り出すための「引き出し」の形や使い方を決めている)。ストレージ上のデータを、ファイルという単位で管理します。ある一定のファイルをまとめる単位をディレクトリと言います(他のOSでいう「フォルダ」と同じものだと思ってもらって良いです)。LinuxはFHS(Filesystem Hierarchy Standard)を採用し、最上位の /(ルート) の下に様々なディレクトリを配置したツリー構造になっています。ファイルシステムには、ext4、xfs、zfsなど様々なものが存在しており、機能や処理速度に違いはありますが基本的には上述の /(ルート) を頂点としたツリー状のディレクトリ構造は共通のものとして構成されます。噛み砕けば、皆さんが普段いじっているファイルやフォルダといった仕組みを使うためのシステムがファイルシステムと言っていいでしょう。
各種ファイルシステムの種類や特性については興味があれば調べてみてください(なお、ファイルシステムの種類はLinuCやLPICなどのLinux系の資格では試験範囲に含まれています)。
なおMacOSなどはUnixベースなのでLinuxとディレクトリ構造は近かったりします。Macをお持ちの方はTerminalアプリで確認してみてもいいでしょう(通常のGUIでは見えない領域もあります)。ChromeOSは思いっきりLinux(Gentoo)ベースなので、ディレクトリ構造はLinuxとほぼ同じです(ただしこれも普通の使い方をしてると見れません)。Windowsでは全く異なるディレクトリ構造になっています。
IPアドレスの設定やサブネッティング、ソケット(プログラムとTCP/IP、プロセスとプロセスを結ぶための通信口。OSI参照モデルでいうトランスポート層)の管理や通信の処理などを行います。
序2-3-3. そのほかのOS機能
Linuxのカーネルの特徴や機能について記述してきましたが、ここまでの内容はあくまでカーネルの機能、つまりは最低限のものです。実際に提供されているOSに備わっている機能にどのようなものがあるかも知っておきましょう。
OSを起動するためのソフトウェアです。PCで電源が投入されると、BIOSによるデバイスの初期化、ブートデバイスの決定、ブートストラップのロード、ブートローダの実行と経てからOSが起動します。
BIOS(UEFI)は前章で記載しましたが、マザーボードROM上に書き込まれているファームウェアです。起動時に、BIOSの初期化プログラムが各種デバイスの初期化を行います。この動作をPOST(Power On Self Test)と呼びます。デバイスの初期化が行われた後、起動用ドライブを検索します。HDDやSSDといったストレージメモリだけでなく、USBやCD-ROMなどのリムーバブルメディアも検索対象です。起動可能なドライブがあれば、それがブートデバイスとして決定されます。
続いて、BIOSがブートドライブのMBR(Master Boot Record)をロードします。MBRはブートドライブの先頭セクタ(先頭部分、みたいに思ってください)のことです。このMBRにブートストラップローダというプログラムが含まれており、BIOSはブートストラップローダに制御を移します。
ブートストラップローダはブートローダ内のパーティションテーブルを探索し、起動フラグのあるパーティションを検索します。パーティションについては別途説明しますが、簡単に言えばデバイスのメモリを用途に沿って分割したものだと思ってください。デバイスの中にOS起動用の領域があり、それを探索します。この起動用のパーティションの先頭セクタであるPBR(Partition Boot Record)に制御が移ります。
PBR内にはIPL(Initial Program Loader)というプログラムが含まれ、このIPLがブートローダを読み込み、ブートローダがOSをロードします。
Linuxのデフォルトブートローダとして、GRUB(GRand Unified Bootloadar)やLILO(LInux LOader)といったものがあります。2つのブートローダの特性についてはここでは割愛します。
接続された外部デバイスなどの制御を行うためのソフトウェアです。単に「ドライバ」と呼ばれることもあります。例えばPCにスマホをUSBケーブルなどで接続するとPC上でスマホが認識されますが、これはドライバによってスマホが認識されているためです。一般的にはハードウェアごとに個別のドライバが必要となり、同メーカーの外部デバイスでも仕様が大きく異なれば本来はその機種用のデバイスドライバが必要となります。しかし現在ではOSに付属している汎用の標準ドライバ(ジェネリックドライバ)を使い、わざわざ専用ドライバをインストールせずとも接続した機器を制御できることの方が多くなっています。
応用ソフトウェアで、CUI上でユーザーからのコマンド入力を受け付けます。いわゆるコマンドラインと認識されるインターフェースはこのシェルによって提供されています。カーネルはソフトウェアとハードウェアの橋渡しを行いますが、シェルは入力装置とカーネルの橋渡しです。ユーザーはシェルでコマンドを入力することでプログラムを実行できます。シェルにも種類が存在し、一般的なLinuxディストリビューションではデフォルトでbashが採用されています。そのほかにもsh、fish、ash、zshなどのシェルが存在し、シェルごとに操作体系などが異なります。
また、シェルスクリプトを利用するとシェルで行える操作や一連の作業を自動化することが出来ます。いわゆるマクロやバッチと呼ばれるものと同等です。
Linuxの操作をGUIで行いたい場合に導入します。ディストリビューションによっては、最初からGUIに対応しています。CUIメインのサーバ向けディストリビューションでも、やろうと思えばGUIを導入してデスクトップPCとして利用することは可能です(そこまでするなら最初からデスクトップ向けのディストリビューションを使えばいいのですが、ただのロマンです)。
Linuxではデスクトップ環境を様々なものから選ぶことが出来ます。1台のLinuxマシンのUIをWindows風にも、Mac風にも変更することが可能で、選んだデスクトップ環境によってOSの使用感が全く異なります。好みのデスクトップ環境を見つけるのもLinuxの楽しさの1つと言えるでしょう。Linuxでデスクトップ環境を使用するにはまずX Window Systemを導入する必要がありますが、最近のディストリビューションではインストール時にGUIを使うか使わないかを選べるものが大半です。
デスクトップ環境はGNOME、KDE Plasma、Xfce、LXDE、MATE、Cinnamon、Budgieなど多種に渡ります。美しさ重視や軽さ重視など、デスクトップ環境ごとに特色があるので好みに合わせてインストールします(専用のデスクトップ環境を持つディストリビューションもあります)。ググってみると、それぞれのデスクトップ環境がどういうものなのかを画像付きで紹介しているページがたくさんあります。
デーモン(Daemon)とはプロセスの一種です(DemonではなくDaemon、悪魔ではなく守り神です)。サーバーのシステム維持やサービス提供のためメインメモリに常駐しているプロセスがデーモンと呼ばれます。いつでもサーバ上で待機していて、外部からリクエストがあればそれに対応してサービスを提供します。サーバをお店とするならば、デーモンは店員のようなものです。
デーモンとして動作しているプロセスは、httpd、sshdなど末尾にdが付いていることが多くなっています。例えばhttpdが動作していればそのサーバーはWebサーバーとして動作し、ユーザーはサーバーのIPアドレス、あるいはURL(FQDN)にアクセスすることでWebページを取得することができます。