プログラムの実行手順とLinux関連の用語について
Linux周りの概要について調べたことをだらだらと書いてみる。
コンピューターシステムの概要
まずコンピューターがプログラムを実行する流れ。
まず、プログラムを実行する。
プログラムのデータが格納されている補助記憶装置(ストレージデバイス)から主記憶装置(メインメモリ)にプログラムをロードして、CPUがメインメモリに格納されたプログラムの指示に従って動作する。
演算結果はメモリに戻され、必要に応じてストレージに戻される。
OS
OSがする仕事は大きく分けて2つある。
1つは、CPUやメモリ、ストレージなどの各種資源の管理。
もう1つは、外部入出力機能の管理である。外部入出力には単にファイルの読み書きやストレージの読み書きだけでなく、ネットワークやプロセス間通信も含まれる。
カーネル
CPUのカーネルモードで動作するOSの中核的な処理をまとめたプログラム。
プロセスはカーネルが提供する機能を使う場合は、システムコールを呼んでカーネルに処理を依頼する。
CPU
メモリにロードしたプログラムの命令に従って処理を進める装置。
カーネルの操作をするカーネルモードとユーザーモードの2つのモードがある。
メモリ
一時的に作業データを保存する記憶領域のこと。
システムコール
システムコールとは特権モードでOSの機能を呼ぶこと。プロセスからカーネルに送られる。 もしシステムコールがなければ、OSの機能を使えないので何もできない。
シグナル
カーネルからプロセスに対してイベントの発生を伝えるもの。
用途としては大きく分けて2つある。
1つは、プロセス間で通信する際に、カーネルがプロセスにシグナルを送信することで通信する。
もう1つは、システムで発生したイベントをシグナルとしてプロセスに送る。例えばControl+C
でデバイスからプロセスを止めるときなど。メモリ範囲外アクセスのエラーでCPUでエラーが発生→カーネルがシグナルを生成し、プロセスを止めるというのも一例。
CPUの動作と高速化
一般にコンピューターの各動作の所要時間の関係は、CPUの計算処理の所要時間 < メモリアクセスのレイテンシ < ストレージデバイスへのアクセスのレイテンシ
である。
キャッシュメモリ
レジスタ上での計算とメモリアクセスの所要時間の差を埋めるためにキャッシュメモリが利用される。
メモリからレジスタにデータを読み出す際はキャッシュメモリにデータを読み出した上で、同じデータをレジスタに読み出す。
ページキャッシュ
CPUからのメモリアクセスとCPUからストレージへのアクセスの所要時間の差を埋めるためにカーネルのページキャッシュが利用される。
ページキャッシュはストレージデバイス上のデータをメモリにキャッシュする。
カーネルはストレージデバイス上にあるファイルデータをプロセスに割り当てたメモリに直接コピーするのではなく、カーネルのメモリ上にあるページキャッシュという領域にコピーしてから、プロセスのメモリへコピーする。
ファイルシステム
Linuxではデバイスも含めほぼ全ての対象をファイルとして表現して操作する。
ファイルにはデータを保持する通常のファイルと、ファイルを保持するディレクトリ、デバイスをファイルとして表現したデバイスファイルの大きく分けて3種類がある。
各デバイスファイルは/dev
配下に存在する。
ジャーナリング
データの不整合を防ぐ仕組みの1つ。
処理の一覧をファイルシステム内のジャーナル領域に書き出す。ジャーナル領域の内容に基づいてファイルシステムの内容を更新することで、途中で電源が落ちるなど処理が中断されても、再起動後にジャーナルログを最初から再生することでファイルシステムは整合性を保った状態になる。
procfs
システムに存在するプロセスについての情報を管理するファイルシステムで/proc
にマウントされる。
ps
コマンドやtop
コマンドなどはprocfsの情報を可視化している。
/proc/${PID}/maps
はプロセスのメモリマップ(仮想メモリ)/proc/${PID}/stat
は指定したプロセスがこれまでに使用したCPU時間やメモリ量などを管理
その他のLinuxのしくみ
Unixドメインソケット
ソケットとは、アプリケーション層からトランスポート層を使うときのインターフェースで、プロセス間通信の1種。
UnixドメインソケットはPOSIX(UNIX系のOSに共通する機能についての規約)系OSで提供されている。Windowsにはないので注意。
Unixドメインソケットを使うことで、高速な通信が可能になる。TCPやUDPなどのソケット通信は外部のネットワークに繋がるインターフェースに接続するが、Unixドメインソケットはカーネル内部でしか使えない。ソケットファイル(.sock
)によって通信する。
サーバーとNiginxなどのリバースプロキシ間の通信の高速化などに利用される。
パイプ
パイプはプロセス間の入出力を繋げる仕組み。
無名パイプ
無名パイプは、コマンド間の入出力を繋げる際に使う。
ps aux | grep go
パイプの前のコマンドの標準出力を後ろのコマンドの標準入力にする。前から後ろに一方行にデータが流れる。
名前付きパイプ
ファイルのように名前でアクセスできるFIFOの性質を持った双方向パイプ。
データを移動したい時などに利用することが多い。 一旦ファイルにデータを書き出す場合と比べて消費するストレージが小さくて済むなどのメリットがある。
スループットとレイテンシ
スループットは、単位時間あたりの仕事量で、高いほど良い。CPUのリソースを使っているほど高くなる(アイドル状態のCPUが少ないほど高くなる)
レイテンシは、処理の開始から終了までの経過時間で、短いほど良い。
スループットが高い状態だとレイテンシは長くなり、スループットが低い状態だとレイテンシは短くなるので、トレードオフの関係にある。