『Linuxのしくみ』読書メモ

*1

ざっくり

CPU/メモリ/ストレージデバイスという構成とか、プロセススケジューリングとかスワッピングとかのトピック自体は知っているものも多かったけど、全体的に解像度がぐっと上がった気がしてよかった。

書いてあって知ったこと

  • CPUのモード

  • システムコール

  • 各種コマンド

    • sar(system admin reporter)でいろいろ
    • freeでメモリ
    • df(disk free)でディスク
  • プロセスにnice(2)で優先度をつけると、プロセススケジューリングにおいてより多くの/少ないCPU時間を割り当てることができる

  • 仮想メモリと物理メモリがある

    • プロセス(カーネルの外、ユーザーの世界)から物理メモリに直接アクセスする方法はない
    • 仮想メモリと物理メモリの紐付けはページテーブルによって管理される
    • 仮想メモリと物理メモリを分離することのメリットは以下
      • 物理メモリ上で断片化せざるを得なかったとしても、仮想アドレス上では連続しているので大きなひとかたまりのデータをもつことが可能
      • 「各プロセスは、そのプロセスのページテーブルに記載された物理アドレスにしかアクセスできない」というルールを導入して、各プロセスが自身と関係ない物理メモリにアクセスすることを防げる
      • プログラムファイルはコード領域とデータ領域をメモリ上のどこにどれだけ確保するかという情報をもつ。物理メモリしかない場合、同じプログラムを複数のプロセスで実行すると、物理メモリ上のある領域を複数のプロセスがそれぞれ勝手につかおうとして困ってしまう。仮想メモリを挟むことによって、物理メモリとしては異なる領域を参照させ、干渉を避けることができる。
    • 仮想メモリの割当はmmap(2)によって行い、割り当てた時点では物理メモリは割り当てられない。メモリへのアクセスが発生して「対応する物理メモリないじゃん!」でページフォールトが起きたら、カーネルページフォールトハンドラが物理メモリの割当(とページテーブルの書き換え)を行う。
    • ページテーブルをコンパクトにするため以下の仕組みがある。
      • 階層化して、対応する物理アドレスがない範囲については、その範囲に対応する下層のテーブルをそもそも作成しない
      • 仮想/物理メモリの対応関係が複数ページにわたって連続している場合、それらページをまとめて一単位(ヒュージページ)として対応関係を保持することでテーブルサイズを小さくする
  • キャッシュメモリにも階層がある

  • キャッシュメモリとページキャッシュは「書き込みがあったらキャッシュを書き換えてダーティー状態にしといて、後でライトバック」とかの点で同型

  • ハイパースレッドは以下の仕組み

    • CPUと(キャッシュ)メモリとの間でのデータ転送待ち時間の分CPUをアイドルにしないために
    • 1つの物理CPUに、プロセスAのデータ転送待ちの間にプロセスBを処理させる
    • これを「論理CPU XがプロセスAを、論理CPU YがプロセスBを引き受けている」状態として表現する
  • バイスはファイルとして表現され(/dev/配下など)、以下の2種類がある

    • キャラクタデバイス: 読み書きできるがランダムアクセスできない。端末やキーボードなど
    • ブロックデバイス: 読み書き及びランダムアクセスできる。ストレージデバイスなど
  • ブロックデバイスにアクセスするには以下2つの方法がある(どちらもカーネルを介する)

  • ブロックデバイスのIOパフォーマンスを良くするために、カーネル内のブロックデバイス層が以下の機能を提供する

    • 先読み: ある領域にアクセスするとつづけて後続の領域が必要になることがおおいので、言われなくてもついでに後続の領域を読み込んでおく
    • IOスケジューラ: IOの指示をちょっとためて、アクセスする領域についてソートしたり連続部分をマージしたりしてからまとめてアクセスする
  • ブロックデバイスのIOパフォーマンスをよくするには

    • HDDでもSSDでも、シーケンシャルアクセスの場合は先読みでかなりパフォーマンスが上げられるので、なるべくシーケンシャルアクセスしよう
    • (どうせその領域全体が必要になるなら)細切れではなくなるべくまとめてアクセスしよう

書いてなくて知ったこと

  • macOS(Mojave)にはtop, dfはあるけどsar, freeはない

  • バイナリの置き場所

    • /bin: 非常時(シングルユーザーモード)でも利用できる必要があるコマンド
    • /usr/bin: RPMdebなどのパッケージ管理システムによって、システムに管理されるコマンド(apt-get, yum
    • /usr/local/bin: RPMdebなどのパッケージ管理システムによってシステムに管理されないコマンド(homebrew)
    • いずれもsbinはシステムから叩くコマンド
  • 標準ライブラリは、コンパイラがデフォルトでリンクしてくれるから「標準」

  • Rubyのコードは以下の手順でシステムコールを呼び出す

次は

ここらへん読みたいな

*1:この要約には違法性はないと考える。https://www.bengo4.com/c_1015/c_17/c_1263/b_341980/