【技術書紹介】［試して理解］Linuxのしくみ

## 書籍情報
書籍名：［試して理解］Linuxのしくみ
著者名：武内覚

https://gihyo.jp/book/2022/978-4-297-13148-7


## 本書を選んだ背景
Linuxについて基本的な知識はありましたが、プロセス管理やメモリ管理といった分野についてさらに深掘りしたいと考え、本書を手に取りました。
またコンテナ技術に興味があり、その基盤としてLinuxカーネルの仕組みを理解することが不可欠だと思ったのも、本書を選んだ理由です。

## 本書について
本書は、実験用のソースコード（Go言語とPython）が提供されており、実際に手を動かして学べる構成なっています。
さらに、図やグラフも多く用意されているため、内容がわかりやすく、資格的にも理解が深まります。

## 本書の内容
以下、個人的なメモを残します。
### 1章 Linuxの概要
- 用語について説明。プログラムとプロセス、カーネル、システムコール、ライブラリ

### 2章 プロセス管理（基礎編）
- プロセスの生成。fowk（）関数でプロセスを2つに分裂、execve（）関数で別のプログラムを起動
- プロセス終了。exit（）関数を呼ぶとexit_group（）というシステムコールを呼ぶ。プロセス終了後は、親プロセスがwait（）系システムコールを呼び、プロセスの戻り値によりエラーログ出力などの対処ができる
- プロセスの状態。システムに存在するプロセスはほとんどがスリープ状態。何もしない

### ３章 プロセススケジューラ
- 経過時間と使用時間。1つの論理CPUを使う場合、並列度が2-3倍になるに従って、使用時間はそれほど変わらないが経過時間は2-3倍になる。複数の論理CPUを使う場合、すべてのプロセスについて使用時間と経過時間がほぼ同じになる
- タイムスライス。1つの論理CPU上で複数の処理が動作している場合は、それぞれの処理が数ミリ秒単位のタイムスライスでCPUを交互に使っている
- 性能。十分な数のプロセスを実行してはじめてスループットが向上する。むやみにプロセス数を増やしてもスループットは上がらない

### ４章 メモリ管理システム
- メモリの回収処理。システム負荷が高まると、カーネルのメモリ管理システムはディスクからデータを読み出してからまだ変更していないページキャッシュを回収する。それでもメモリが足りない場合はout of memoryが発生、oom killerによりプロセスを強制終了する
- 仮想記憶における問題。メモリ断片化、マルチプロセスの実現が困難、不正な領域へのアクセス。不正なメモリアクセスが行われると、ページフォールトが起こる
→プロセス毎に仮想アドレス空間を作れば、マルチプロセスの実現と不正な領域へのアクセス対策ができる
- メモリ領域の割り当て、mmap（）システムコール
- メモリの割り当て、デマンドページング。ページフォールトが発生しても、カーネルのページフォールトハンドラが動作してページに対応する物理メモリを割り当てる。メモリ領域を獲得してからアクセスするまで、仮想メモリの使用量が増えるが物理メモリ使用量は増えない。メモリアクセス中にページフォールトの数が増える、それに加えてアクセス完了後の物理メモリ使用量は増える

### ５章 プロセス管理（応用編）
- folk（）関数の高速化はコピーオンライトという。各ページへの初回書き込み時にデータをコピー。これによりメモリをフルコピーしなくて済むためfolk（）関数を高速化でき、またメモリ使用量を減らせる
- execve（）関数の高速化はデマンドページングにより実現
- プロセス間通信。共有メモリ、シグナル、パイプ、ソケット
- 排他制御。flockコマンドでファイルロック

### 6章 デバイスアクセス
- プロセスがデバイスにアクセスする方法について、カーネルがデバイスファイルを介してアクセスする。その際に動作する機能がデバイスドライバ
- ポーリングと割り込みについて、デバイスの処理完了をすぐに検出できる点で割り込みのほうが扱いやすい
- デバイスファイル名は変わりうるため、systemdの udevが作る「persistent device name」という名前を利用する

### 7章 ファイルシステム
- ストレージデバイスはファイルシステムを介してアクセスする
- 内部的にPOSIXに定められた関数を呼び出しているため、ユーザはファイルシステムの違いを意識しなくてよい
- メモリマップトファイルは、ファイルの領域を仮想アドレス空間にマップする。メモリマップしたファイルにはメモリと同じ方法でアクセスできる
- ファイルシステムの整合性保持には、ジャーナリングとコピーオンライトが広く使われる

### 8章 記憶装置
- CPUとメモリの間にキャッシュメモリを介することで、メモリへのアクセスはせずにキャッシュメモリへのアクセスだけで済むため、データの読み出しを高速化できる
- メモリへの書き込み方法は、データをキャッシュメモリに書き込むときにメモリにも一緒に書き込むライトスルー、後ほど所定のタイミングで書き戻すライトバック。ライトバックのほうがCPUからメモリへのデータ書き込み命令の実行にメモリアクセスせずに済むため、高速化できる
- ダーティとは、メモリへの書き込みの前にキャッシュメモリに書く。 この時キャッシュラインには、メモリから読み出してからデータが変更されたことを示す印をつける。このような印をつけられたキャッシュラインを「ダーティである」と表現する
- キャッシュに入っていない領域へのメモリアクセスが頻発すると、キャッシュライン内のデータが激しく入れ替わる。これをスラッシングといい、性能が劣化する
- 参照の局所性。近い将来に再びアクセスする可能性が高い
- 階層型キャッシュメモリ。最近のCPUはキャッシュメモリが階層化されていることがある
- CPUの計算リソースが空いていると、SMTで有効活用。1つの物理コアを複数の論理スレッドとする
- ページキャッシュはキャッシュメモリに似ており、ダーティやライトスルーライトバックがある
- バッファキャッシュはファイルデータ以外のものをキャッシュする仕組み
- スワップは物理メモリに空きがないときストレージ内のスワップ領域を使って空きを作る。物理メモリの中でしばらく使わないであろうとカーネルが判断したメモリをスワップ領域に書き増す。これをページアウト。空きメモリができるとプロセスがページアウトしたページにアクセスすると、対応するデータを再びメモリに呼び出し。これをページイン
- 統計情報。sarコマンド

### 9章 ブロック層
- HDDの読み書きについて。I/Oスケジューラはマージとソートにより最適化処理をしI/O要求する。先読みは後続領域をページキャッシュに保存しておく機能
- スループットは単位時間当たりのデータ転送量。レイテンシは1回当たりのI/Oに要する時間。IOPSは1秒間に処理できるI/Oの数
- ブロック層が性能に与える影響をfioを使って確認する。I/Oスケジューラを有効なときは、IOPSが高くレイテンシも下がる。先読みが有効な場合は、無効な場合と比べて性能が2倍以上高くなる
- HDDと比較して、NVMe SSDの場合はI/Oスケジューラが有効なほうが性能が低い。NVMe SSDのような高速なデバイスの場合は、I/OスケジューラのためにI/O要求を溜めておくコストがHDDに比べて相対的に高いため

### 10章 仮想化機能
- 物理マシンの処理をするVMX-rootモード、仮想マシンの処理をするVMX-nonrootモード
- PCPU0上ではVCPU0スレッド以外はほぼ何も動いていない。VCPU0のプロセス0とプロセス1のいずれも進捗がない時間は、PCPUのプログラムが動く
- sar -P 0 1における%stealというフィールドは、VCPUが動作しているPCPU上で、VCPU以外のプロセスが動作している割合を示している
- 仮想マシン上のファイルに書き込む性能は、物理マシンに比べて大幅に劣化する。そのため準仮想化技術でストレージI/Oを高速化する
- 準仮想化は仮想化ソフトウェアと仮想マシンを特別なインターフェースで接続することによって性能改善する
- virtio-blkは、ホストOSとゲストOSが共有するキューを用意、キューにコマンドを挿入しこれをホストOSの仮想化ソフトウェアが取り出して処理することでI/Oを高速化する

### 11章 コンテナ
- 仮想マシンとコンテナを比較すると、コンテナを作った上で最初のプロセスを起動するだけでよいため、起動時間とハードウェアへのアクセス速度がコンテナのほうが早い
- pid namespace。root pid nsから子pid nsは見えるが、子pid nsから親pid nsは見えない。お互いに見えない独立したnsを持つことで他のプロセスと実行環境が分かれている1つないし複数のプロセスがコンテナの正体

### 12章 cgroup
- システムのメモリやCPUなどのリソースをどのプロセスにどれだけ与えるか細かく制御する

## 本書の感想
ハンズオン形式で体系的に学べるうえ、図やグラフも豊富で、Linuxの理解がしやすい内容となっています。
Linux初学者だけでなく、これから仮想化技術やコンテナについて学びたい方にもおすすめの書籍です。