ただの技術メモ

個人備忘録

Linuxのプロセス管理

Linuxのプロセス周りについて自分なりにまとめてみる。

プロセス

プロセスとはコンピューターシステムのプログラムの実行単位。 プロセスはOS上で実行中のプログラムを指し、プログラムの実行単位である。 OSがファイルを実行する際にメモリやCPUなどのリソースを確保・消費してプロセスを生成する。

プロセスの生成方法

実行ファイルを読み出してプロセスのメモリに必要な情報を読み出す通常のプロセス生成で利用される。

1つのプロセスをもとに新たにプロセスを生成する際に利用される。 子プロセス用のメモリに元になる親プロセスのメモリをコピーすることによって実現する。

Apacheでは複数リクエストを捌くのにfork()を使っており、リクエストが増えたときに処理できない場合はある(C10K問題(クライアント1万台問題))

ファイルディスクリプタ

カーネルは各プロセスでどういった入出力が行われるかを管理する必要があり、各プロセスが関与しているファイル情報のリストを持っている。 ファイルディスクリプタはそのリストのインデックス値であり、識別子として利用される。ファイルディスクリプタ(インデックス値)を指定することで対応するファイルにアクセスできる。

OSはプロセスが生成されるとまず3つの擬似ファイルを作成し、それぞれにファイルディスクリプタを割り当てる。0が標準入力、1が標準出力、2が標準エラー出力。 そのプロセスでファイルやソケットをオープンするたびに対応するファイルディスクリプタはインクリメントされる。

bashのプロセスのファイルディスクリプタを確認してみる。

まずbashのプロセスのIDを確認する。

$ ps aux | grep bash
root        9091  0.0  0.0   3864     0 pts/0    Ss+  Jun01   0:00 bash

ファイルディスクリプタの情報は/proc/${PID}/fd/に含まれている。

$ sudo ls -al /proc/9091/fd/
total 0
dr-x------ 2 root root  0 Jun  4 14:17 .
dr-xr-xr-x 9 root root  0 Jun  4 14:17 ..
lrwx------ 1 root root 64 Jun  4 14:17 0 -> /dev/pts/0
lrwx------ 1 root root 64 Jun  4 14:17 1 -> /dev/pts/0
lrwx------ 1 root root 64 Jun  4 14:17 2 -> /dev/pts/0
lrwx------ 1 root root 64 Jun  4 14:17 255 -> /dev/pts/0

これを見るとbashの場合は、0 1 2は全て/dev/pts/0へのリンクになっている。

デーモンプロセス

デーモンとはバックグラウンドプロセスを作るための仕組みのこと。 一般的なプロセスはシェルの子プロセスとして生成されるのでログアウトしたりシェルを閉じてしまうと終了してしまう。

デーモン化は、プロセスの作業ディレクトリをルートに移動させて、プロセスをforkしてから親プロセスをsystemd(初期プロセス)に変更し、元々の親プロセスは終了させることで作成する。標準入出力もプロセス生成時のものから通常は/dev/nullに変更して捨てる。

$ ps -ef | grep daemon
UID          PID    PPID  C STIME TTY          TIME CMD
message+     718       1  0  2021 ?        00:00:27 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation --syslog-only
daemon       745       1  0  2021 ?        00:00:00 /usr/sbin/atd -f
hysrtr   1396238 1396202  0 23:57 pts/1    00:00:00 grep --color=auto daemon
root     2626495       1  0  2021 ?        00:02:55 /usr/lib/accountsservice/accounts-daemon

※systemdはサービスを起動するための初期プロセスで、カーネル(PID=0)から起動され、PIDは1になっている。

$ ps aux | head -n 5
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  1.5 169084  7388 ?        Ss    2021   6:57 /lib/systemd/systemd --system --deserialize 57
root           2  0.0  0.0      0     0 ?        S     2021   0:01 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<    2021   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<    2021   0:00 [rcu_par_gp]

スレッド

スレッドは1つのプロセスから生成され、スレッドを使うことで並行処理を実現できる。

親プロセスと同じメモリ空間を使用し、同じプロセスのスレッド同士はお互いのメモリ領域にアクセスできる。 一方でプロセスは固有のメモリ領域を持っているので別プロセスのメモリ領域にはアクセスできない。

プロセススケジューラ

複数プロセスの実行はプロセススケジューラによって管理されている。

一般に1つのCPU上で同時に処理できるプロセスは1つだけで、プロセススケジューラによって複数プロセスが同時に動作しているように見える。

※マルチコアCPUでは1つのコアが1つのCPUとして認識される。

つまり、CPU上ではプロセスを順番に1つずつ動かして1周したらまた最初のプロセスから動かすラウンドロビン方式でプロセスは動作している。

ラウンドロビン方式とはCPUを使用できる時間を定め、その時間内に処理が終わらない場合は次のタスクにCPUの使用権が与えられる方式。

CPU上で動作するプロセスが変わることをコンテキストスイッチという。