はぜにっき

日記です。(毎日更新ではない)

「試して理解 Linuxのしくみ」 読んだ

はぜです.

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

読みました.


自分について

買おうか悩んでいる人向けに参考程度ですが, 自分の情報を書いておくと

という感じです. 所謂「スーパーマン」ではない.
プログラミング自体には長く触れているが, 「がっつり」ではない. ゆるふわエンジニアです.

自宅サーバはこの前破棄しちゃったのでmacで可能な限り試した. 他に動いている処理が結構あるので正確な実験ではないだろうけど, まあ良いでしょう.

以下, 各章ごとの自分用メモと簡単な感想


1章 コンピュータシステムの概要

  • アプリケーション, ミドルウェア, OS, ハードウェアの繋がりの話
  • なぜ「ドライバ」が必要なのか?
  • ユーザモードとカーネルモードの話

大体知ってた. そうだねーっていう感じで軽く読み飛ばし.
文章も図もまとまっていてわかりやすい. 人に説明するときに参考にしたい.

2章 ユーザモードで実現する機能

  • OSの機能とかプロセス発行をしたいときはシステムコールを使ってカーネルモードで処理をするんだよっていう話
  • strace を使ってHello,World!を表示するときにどんなコールが呼ばれているかを確認
  • sar コマンドでユーザモードとカーネルモードのどちらでプロセスを実行しているかを確認する
  • システムコールのラッパー, OSが提供するライブラリとプログラムについて

strace コマンド初めて知った. すごい. よくわからない
無限ループでシステムコールを使う処理を回した時の実験は, 思ったよりuser率高いなーという感想.

3章 プロセス管理

  • fork()について

    • 子プロセス用のメモリ領域を作る
    • 親プロセスのメモリ領域を子プロセスのメモリ領域にコピー
    • 親と子が別々の処理として動く
  • execve()について

    • 実行ファイルを読んで, その内容を実行中のプロセスに上書き
    • 実行
    • プロセス数は増えない.
    • readelf でコマンドの開始アドレスを見る
  • 実行時に生成されたプロセスのメモリ情報(マップ)は /proc/[pid]/maps に書き出される

  • プログラムを終了するには _exit() システムコールが使われる

いわゆる forkexec の話.
forkはすぐイメージできるけど, execは別プロセス化して動くっていうのがなんとなくイメージ付きづらいところがある.

4章 プロセススケジューラ

  • taskset ... 指定したプログラムを指定したCPU上でのみ動作させるコマンド
  • 複数のプロセスを1CPUで同時に実行させた時の進捗度合いを実験する

    • 一定時間ごとにプロセスが順番に切り替わっていく(コンテキストスイッチが発生する)ことを確認
    • 実行が完了する時間はプロセスが増える分に比例して増えていくことを確認
  • 実行状態, 実行待ち状態, スリープ状態, ゾンビ状態について

  • アイドルプロセス: 何もしないことでCPUを休止状態にし, 消費電量を抑えた状態にするプロセス

  • スループットとレイテンシについて

    • スループット: 実行完了プロセス数/経過時間
    • レイテンシ: 実行完了時間 - 実行開始時間
  • 複数CPUでの複数プロセス同時実行 

  • nice(): 優先順位
    • 優先順位を下げることは誰でもできるが, あげるのはroot権限持ちユーザのみ

プロセスの実行順序と掛かる時間についてのお話.
頭の中では理解しているが, 実際にグラフを見ると面白い. 実際こんな綺麗に結果が出てくるものなんだなーと思った.
macの上にvagrant/virtualboxCentOSを立ち上げてやってみると, 書籍に書いてあるほど綺麗ではないがそれっぽい挙動を見ることができた.

5章 メモリ管理

  • free コマンドでメモリの状態を見る
  • OOM Killer 「君はたぶんいらない子
  • 仮想記憶の仕組みを用いない単純なメモリ割り当ての問題点

    • メモリの断片化
    • 割り当てられた領域以外の領域へのアクセス可
    • メモリの断片化によるプロセスのメモリ配置ができなくなる問題
  • 仮想記憶について

    • プロセスから見えるアドレスを仮想アドレス, 自裁のアドレスを物理アドレスと呼ぶ
    • ユーザが物理アドレスを確認する方法はない: 見れたら他の領域へのアクセスが可能になるかもしれないので
    • カーネルが使うメモリ領域の中にある「ページテーブル」で管理する
    • もらった領域の外にアクセスしようとするとSIGSEGV(ページフォールト)が発生してプロセスは強制終了される
    • 追加割り当てはプロセスが要求(mmap)すれば, 対応するページテーブルを作成して仮想アドレスをもらえる
  • ファイルマップ

  • デマントページング

    • 領域を確保したが, ユーザに使われなかった領域が出た場合に他のプロセスにその領域を割り当てる機能
  • 仮想メモリ, 物理メモリの枯渇

  • forkの高速化

    • forkシステムコール実行時には親プロセスのメモリを全てコピーするのではなく, ページテーブルのみをコピーする
    • どちらかがメモリ上への書き込みを行おうとした場合にはページフォールトが発生し, 新しく物理ページが用意され書き換えられる
    • コピーオンライト(CoW)と言う
  • スワップ

  • ヒュージページ

    • ページテーブルの中身が増えてくるとforkシステムコールが遅くなる
    • ページテーブルを階層化して一度で見なければならない範囲を減らすことで高速化する
    • トランスペアレントヒュージページという, 仮想アドレス空間内の連続する4KBのページを良い感じにヒュージページにしてくれる機能があるけど使わない様にもできる

普通に知らないことが多くて良い. デマントページングとか初めて聞いた.
OOM Killerとかswapとかは仕事でサーバ削減をしていたときに結構気を付けていたので知ってはいたが, ぼんやりした理解だったので確認.
ちゃんと理解して使えるようになりたいと思う反面, この辺を真面目に意識してプログラムを書く機会ってそんな無いよなあ と思ってしまう.
メモリを極力使わないようなコードを書くとか, メモリ領域に合わせて使う分を考えてとかはやると思うけど. 忘れないようにしたい.

6章 記憶階層

  • レジスタ
  • メモリキャッシュ
  • メモリ
  • ストレージデバイス

    • の速度の話
  • キャッシュメモリの話, 階層型の話

  • 参照の局所性

    • 時間的局所性: アクセスされたデータは近いうちに再びアクセスされる可能性が高い
    • 空間的局所性: 次にアクセスされるデータは, 前回アクセスされたデータの近くにある可能性が高い
  • Translation Lookaside Buffer

    • ページテーブルを参照して, 仮想アドレスを物理アドレスに変換する処理を高速化するための領域
    • 詳細はぐぐる
  • ページキャッシュ

    • ストレージ上のファイルデータをメモリにキャッシュする.
    • ダーティページの説明
    • open()でファイルを開くときにO_SYNCフラグを立てると可能な限り同期書き込みをする
    • vm.dirty_writeback_centisecs パラメータでダーティページのライトバックを行うタイミングを変更できる
    • /proc/sys/vm/drop_caches
    • ハイパースレッド

プログラムの高速化, ISUCONでよく考える系の話. fujiwaraさんの資料がとてもわかりやすくて良い.
http://isucon.net/archives/50648750.html

Translation Lookaside Bufferとハイパースレッドがよくわかってないので調べてまとめたい
/proc/sys/vm/drop_cache は仕事でお世話になった.

7章 ファイルシステム

  • 雑に言えばファイル名/場所/サイズ のリレーションを保管しておいてくれるもの
  • ユーザモードで ファイル名, ファイルのオフセット, サイズ を指定しシステムコールを発行すると, カーネルモードでストレージに行って読み出してくれる
  • Linuxはファイル名の部分をディレクトリを使ったツリー構造で保管

  • データ: 文書, 画像, プログラムなど

  • メタデータ: ファイルの名前とかストレージ上の位置, サイズなどの補助情報

    • df コマンドで表示されるストレージ使用率はデータ+メタデータの総量
  • クォータ: 用途ごとにファイルシステムの使用料を制限する機能

    • ユーザクォータ: ユーザごとに容量を制限する. ext4とXFSで利用可
    • ディレクトリクォータ: ディレクトリごとに容量を制限する
    • サブボリュームクォータ: ファイルシステム内のサブボリューム単位ごとに容量を制限する. Btrfsで利用可
  • mvコマンドによるファイル移動の流れ

    • mv /bar /foo
    • foo -> bar リンクを貼る
    • / -> bar リンクを削除
    • 〜完〜
  • リンクを貼り終わった瞬間に電源が強制的に切られた場合, 二箇所からリンクが貼られた不整合な状態となる

    • マウントで検出したらマウントができなくなる, アクセス中に検出すると読み出し専用モードでの再マウントorパニック
  • シャーナリング

    • ファイルシステム内に, ユーザに認識できないジャーナル領域というものを用意する
    • 更新処理の一覧を書き出す(ジャーナルログ)
    • その内容に基づいてファイルシステムを更新する
    • 更新が完了したらジャーナルログを削除する
  • 更新中に強制断が発生した場合, ジャーナルログを最初から再生することで処理を完了させることができる.

  • コピーオンライト

    • コピーオンライト型のファイルシステムとそうでないものがあり, コピーオンライト型のものは Btrfs など.
    • ファイルを更新するごとに別の場所にデータを書き込むというもの. ext4やXFSは同じ場所に書き込む
    • 更新処理は, 更新された後のデータを別の場所に全て書き込んでから, リンクを張り替える処理となるため, 途中で死んでも作りかけのものを削除すれば大丈夫
  • 不整合で死んだとき: バックアップを戻す or fsck で直す

    • fsckは復旧のためにファイルシステムを全て見るので, システムが大きいとめっちゃ時間かかる
    • 失敗する確率もそこそこある
    • 望んだ通りに復旧する可能性がそんなに高くない(あくまで不整合を直すだけなので)
  • バイスファイルについて

    • Linuxは大体のデバイスをファイルとして認識している(ネットワークアダプタは例外)
    • バイスファイルは, 以下の二つに分類される
      • キャラクタデバイス: 読み/書き ができるもの. マウス, キーボード, ウィンドウなど
      • ブロックデバイス: 読み書きに加え, ランダムアクセスが可能なもの. HDD, SSDなど
  • tmpfs

  • ネットワークファイルシステム

    • いわゆるnfs.
  • 仮想ファイルシステム

    • procfs: プロセスの情報を得るためのもの. /proc以下. maps, cmdline, stat など
    • sysfs: カーネルのプロセスに関係しない情報を置くためのもの. /sys以下. devices, fsなど
    • cgroupfs: cgroupの情報が置かれている. rootのみ使用可
  • Btrfsについて

    • ext4, XFSと異なる部分の紹介
    • マルチボリューム, スナップショット, RAID, データ破損検知と修復機能などがある

この章が一番知らないことが多かった.
journal ってそういう意味のものなのね... というのがこの本読んでの一番の驚きだった. プロセス死んでるときに見るためのログとしか理解していなかった.
普段あんまり意識していないなーという気持ちで読んでいた. 各ファイルシステムのこと(ext4とかXFSとかBtrfs)もある程度は理解しておくべきなんだろうなあ

第8章 ストレージデバイス

  • HDDのセクタ
  • I/O スケジューラについて
    • ブロックデバイスへのアクセス要求をある程度溜めてからアクセスする仕組み
    • 連続するセクタへのアクセスを一つにまとめる, 不連続なセクタへの要求を番号順に並べることで性能を高める
  • 先読みについて

    • ストレージデバイス内のどこかにアクセスした際, 同時にその周りの領域を先に読んでおく機能
    • 空間的局所性
    • 読んでおいたところにアクセスが来なかったら捨てる
  • HDDとSSDの違い

    • SSD: アームもないし回転もしない
    • 比較的高い
    • ランダムアクセスだと差は顕著

基本情報技術者の午前試験思い出した. 懐かしい
HDDはどう動いていて, SSDはどう動いているのかを大雑把にでも理解しておくと, I/Oを考えるときに良いと思う.


数日で, 多少実験しながら読んだ.
覚えるというよりも, 正しく理解するための書籍で, 実験も面白くて良い.
学生のときに読みたかったな. 4月に入ってくる新人の人に貸してあげたりとか, プログラム書いたことあるけどインフラ系触ったことないような人に勧めてみても良い本なんじゃないかなーと思った.