はじめに

バックエンドエンジニアのロードマップに沿ってエンジニアとしての自己肯定感を養うシリーズです。

プロセスとは

プロセスという概念は Linux において、ファイルシステム、ストリームに並んで重要な構成要素の1つです。

プログラマが作成したソースコードはファイルに保存されます。そしてファイルの保存先はハードディスクです。

プログラムの実行時、プログラムはハードディスクからメモリへと読み込まれます。

CPU はメモリに読み込まれたプログラムを順次処理していきます。このとき、メモリに読み込まれて CPU に処理されているプログラムをプロセスといいます。

1つのプロセスを処理できるのは1つの CPU のみです。

そのため、同じプロセスしか一度に実行できなくなるといったことを避けるために、CPU はプロセスごとに処理時間を決めて次々に切り替えます。

普段使っている PC やスマホは Youtube や Line や Twitter など、複数アプリを同時に起動して使用しています。

あれは CPU が処理時間を決めて順に処理しているために実現されています。

OS のコアであるカーネルはプロセスの優先順位を考慮して、各プロセスに処理時間を割り当てます。

(この機能をスケジューラ、またはディスパッチャといいます。)

アドレス空間

プロセス1つに対して、CPU とメモリがそれぞれ1つ必要です。CPU は前述の通り、処理時間を割り当てるのに対し、メモリはプロセスごとにアドレス空間を割り当てます。

メモリにプログラムを書き込む際にはアドレスが必要です。

しかしプロセスには 0 番地から始まるメモリが必要なため、1つのプロセスしか使えなくなってしまいます。

そこでプロセスから見えるアドレス(論理アドレス)と実際のアドレス(物理アドレス)を分けてしまいます。

こうすることで、カーネルと CPU によって論理アドレス → 物理アドレスと変換された実際のアドレスに対して書き込むことができます。

1つのプロセスの論理アドレス、物理アドレスを全体としてアドレス空間といいます。

アドレス空間はプロセスごとに割り当てられるので他のプロセスにアクセスできなくなります。

プロセス API

fork(2)

自分のプロセスを複製して新しいプロセスを作ります。

Github でも fork がありますが、意味合いは同じです。既存のリポジトリを複製します。複製したリポジトリは自由に更新できますが、fork した元のリポジトリに対しては更新はできません。

プロセスの fork は元からあるプロセスを親プロセス、複製されたプロセスを子プロセスと呼びます。

子プロセスの fork 実行時の戻り値は 0 です。

(戻り値 0 は正常終了のステータスコード)そして親プロセスの fork 実行時の戻り値は子プロセスのプロセス ID です。

シェルでもps auxコマンドを使用して確認できます。

exec

プロセスを新しいプログラムで上書きします。fork したプロセスで即座に exec することで新しいプログラムを時刻したことになります。

wait(2)

fork したプロセスの終了を待ちます。

以上で、プロセスのライフサイクルは fork で子プロセスを生成し、exec で実行して wait によって、親プロセス側で終了判定するといった流れになります。

pipe(2)

シェルではパイプ「|」を使って複数のコマンドをつなぐことができます。

言い換えると、パイプはプロセスからプロセスにつながったストリームのことです。(ストリームはバイトの流れ道のイメージ)

pipe を実行すると、1つのプロセスでは、自身の書き込み用から読み込み用のファイルディスクリプタへ一方向のストリームが生成されます。

また、プロセスを fork するとストリームも複製されます。

そこで pipe を実行した後に、fork し親プロセスの読み込み側、子プロセスの書き込み側を close すると、

親プロセスの書き込み側 → 子プロセスの読み込み側への1つのストリームが生成されます。

これがシェルのパイプの原理です。

デーモンプロセス

http サーバや mysql サーバ、いわゆる常駐プロセスと呼ばれるものです。

ps auxコマンドを実行した際、TTY の項目が?になっているプロセスで、制御端末を持たないプロセスのことを言います。

サーバのようにずっと動作し続けるプロセスは、実行したユーザを持たないことで停止されることがなくなります。

(プロセスは、起動したユーザがログアウトするとプロセスも停止してしまうからです。)

余談

プロセスについての情報がなかなか探せない中、本棚に眠っていた良書を思い出して引っ張り出した甲斐がありました。

日々の業務でも触れていますが、 汎用的な知識は重要だと痛切に感じます。

備考

ふつうの Linux プログラミング 第 2 版 Linux の仕組みから学べる gcc プログラミングの王道

表紙イラスト:Loose Drawing