【試して理解】Linuxのしくみ 読んだメモ
忘れないようメモ📝LinuxのシステムをC言語でプログラム書いて色々覗いてみようという本。 個人的に見よう見まねでCを書けて楽しかったし、メモリ操作とかあってハードウェアに近い言語なんだなって体感した。 Cをもう少しやってみたいので、東大でCの基礎を学ぶ講義が公表されているのでこれをやってみようと思います。
1
- Linuxでデバイスを操作する処理をデバイスドライバというプログラムにまとめて、プロセスからデバイスには、このドライバを介してアクセスしている
- BIOS, UEFI: ハードウェア組み込みのソフトウェア。ハードウェアの初期化処理をする
2. ユーザーモード
- プロセスがカーネルの助けが必要な時に、処理を依頼することをシステムコールという。
- ex. プロセス生成・削除、メモリ管理、プロセス間通信、ネットワーク、ファイルシステム操作、ファイル操作 ‐ straceでprint("hello world")のシステムコールを見てみる。C:29行、Python: 514行!Σ(・□・;)
- %systemが数十のように大きな値になっているときは、システムの負荷が高い状態かも。
- 各高級言語ごとに、システムコールのラッパー関数をOSは用意している。
- OSが提供するプログラムは色々ある。コンパイラgcc, スクリプト言語実行環境:pythonなども。
3. プロセス管理
- プロセス生成は2種類
- 同じプログラムの処理を複数プロセスに分けて処理
- fork()(内部的にはclone()):発行したプロセスを元に、新たにプロセスを1つ生成。
- 全く別のプログラムを生成
‐ プロセス数が増えるのではなく、あるプロセスを他のプロセスで上書きする
- execve():
- プログラム実行の流れ:プログラムファイルの情報(補助的情報・コード領域・データ領域)に基づいてメモリ上にマップされる → エントリポイントからプログラムを実行する
- プロセス終了時は_exit()関数を使用。直接呼び出すことは少なく、Cならexit()呼び出しで終了
- 同じプログラムの処理を複数プロセスに分けて処理
4. システムスケジューラ
- 論理CPU上である瞬間に動作できるプロセスは1つのみ
- 複数プロセス実行中の場合、途中でプロセスを切り替えている→切り替えをコンテキストスイッチという
- プロセスのスリープ状態時はCPUはアイドリング状態(使っていない)
- レイテンシ:処理の終了までの所要時間
- スループット:単位時間当たりの総仕事量
- 論理CPU0と、論理CPU/2の番号のものは独立している
- プロセス数を論理CPU数より多くしても、スループットは上がらない
- nice(): 特定のプロセスに優先度を設定する。-19(高い)~20(低い)。優先度を上げられるのはrootのみ
5. メモリ管理
- メモリ使用量が増えて身動きが取れない事:OOM(out of memory), メモリ管理システムはこの時適当なプロセスをkillしてメモリを開放する機能がある。
- sysctlのvm.panic_on_oomが0→デフォルト、killer発動, 1->OOM時にシステム強制終了
- プログラムはメモリが断片化していると、使用できないこともある
- 仮想記憶:物理メモリにプロセスから直接アクセスするのではなく、仮想アドレスを用いて間接的にアクセスすること。仮想アドレス=プロセスから見えるメモリのアドレス。プロセスから物理アドレスに直接アクセスする方法はなし。
- 仮想アドレス≠物理アドレス
- 仮想アドレスと物理 -アドレスの対応表をページテーブルという。サイズは4KB(x86_64アーキテクチャ).
- メモリ割り当て方法
- mmap関数:ページ単位で仮想メモリ取得、大きめメモリをプールしておく→その後malloc関数:バイト単位でメモリ取得
- ファイルマップ:mapp()を所定の方法で呼び出すことで、ストレージデバイス内の該当ファイルをメモリに呼び出す→その空間を仮想アドレス空間にマッピングできる
- デマンドページング:
- コピーオンライト;fork()時は、親プロセスのページテーブルを子プロセスにコピーする(一緒の物理アドレスを指している)この時書き込み権限は無効化されている
- スワップ:ストレージデバイスの一部を一時的にメモリの代わりとして使用する。物理メモリが枯渇した際、使用の一部をストレージに退避させる。メモリを退避させる領域をスワップ領域(windowsでは仮想メモリ)、退避させることをスワップアウトという。取り戻すことをスワップイン、合わせてスワッピングという
- ヒュージページ;プロセスのべージテーブルに必要なメモリ量を減らせる、データベースなど仮想メモリを大量に使用するときに検討すると吉
6. 記憶階層
- コンピュータの動作の流れ
- レジスタのメモリのやり取りのところで時間がかかる→キャッシュメモリを利用
- キャッシュメモリ:基本CPU内にある。メモリのデータをキャッシュメモリにキャッシュする
- ページキャッシュ:ストレージのデータをメモリにキャッシュすること ‐ プロセスがファイルのデータを読み出す場合、まずカーネルのメモリ上のページキャッシュ領域にコピーして情報を保持→そのデータをプロセスのメモリにコピーする.再度呼び出された場合早く呼び出せる。
- ハイパースレッド機能:CPUコア内のレジスタなどを複数用意して、それぞれを論理CPUと認識されるようにするハードウェア機構スループットが単純に倍になるという訳でもない。
- /sys/devices/system/cpu/cpuNum/topology/thread_siblings_list: ペアとなるスレッドの表示
7. ファイルシステム
- どこにどんなデータがあり、どこに空き領域があるか管理する仕組み
- linuxは複数のファイルシステムを扱える(ext4, XFS, Btrfs... ストレージデバイス上に存在する)
- データ(データの中身・内容)とメタデータ(種類・時刻・権限情報)の2種類がある
- ファイルシステムごとに使用できる容量を制限する機能があり、クォータという ‐ ユーザクォータ、ディレクトリクォータ…
- システム不整合を防ぐ方法
- tmpfs: メモリ上に作成するファイルシステム、再起動後はデータが消えている
- mount | grep ^tmpfs
- freeコマンドのsharedフィールドの値はtmpfsによって使用されているメモリ量(KB)
- ネットワークファイルシステム:リモートホスト上のファイルにアクセス。windowsはcifs, UNIX系はnfs
8. ストレージデバイス
- HDD
- SSD
使ったコマンド💻
- strace: プロセスが呼び出すシステムコールをみる
- sar: プロセスがユーザーモードかカーネルモードのどちらで実行しているのかみる
- sar -P ALL 1(1秒ごとに見る) sar -P ALL 1 1(1秒ごとに1回測定)
- ユーザーモード→%userと%niceの合計 ‐ カーネルモード→%system
- sar -q 1 1: runq-szフィールド→実行中or実行待ちプロセス数
- sar -r 1: 1秒ごとのメモリ状況。kbmemused->物理メモリ使用量、kbswpused->スワップ領域の使用量、kbpgtbl->ページテーブルに使用している量, kbcached->ページキャッシュの総量(kb)
- sar -W 1: ``ごとのスラッシング確認、pswpin/sがスワップイン ‐ sar -d -p 1: ストレージデバイスに対するI/O量
- ldd: プログラムがどのライブラリにリンクしているかみる
- ldd /bin/echo ‐ readelf
- readelf -h /bin/sleep: 開始アドレスを表示
- /proc/pid/maps: プログラム実行時に作成されたプロセスのメモリマップ表示、仮想アドレスを表示
- taskset: 指定の論理CPUで動作させる
- task -c 0 ./sched
- ps ax: 動かしているプロセスの確認
- STAT: R->実行or実行待ち状態、S, D->スリープ状態(シグナルによって実行状態に戻るのがS), Z-> ゾンビ状態(親プロセスの終了待ち)
- ps -eo pid,comm,etime,time: 経過時間(elapsed)と使用時間(time)
- grep -c processor /proc/cpuinfo:論理CPUの数
- timeコマンド:CPUの経過時間(real)と使用時間(user + sys,全コアの合計使用時間)がみれる ‐ time taskset -c 0 ./sched 1 10000 10000
- nice -n 5 echo hello: 優先度5でecho helloする
- free: memory容量確認(kバイト)
- swap --show: システムのスワップ領域確認
- cat /sys/kernel/mm/transparent_hugepage/enabled: トランスペアレントヒュー次ページの使用を確認
- df: ファイルシステムのストレージ使用量
- /proc/pid: 各プロセスの情報を得る
- maps, cmdline, stat
- /procにはその他ハード情報が盛りだくさん、詳しくはman procで ‐ /sys: procのようなカーネルのプロセスに関するもの以外の雑多な情報