Linuxのお勉強。

プロセスとは

シェルからコマンドを実行すると、カーネルはディスクから実行ファイルを読み出してメモリに格納し、そのメモリ内容に従ってCPUがプログラムを実行する。
ここで、メモリ上で実行状態にあるプログラムのことを「プロセス」と呼ぶ。

プロセスの仕組み

プロセスは同一のコマンドから実行されていても、それぞれ別個のメモリ領域を持つため、例えば vi コマンドが3つ同時に実行されても、お互いが混ざって実行されたりはしない。

プロセスはファイルのオーナーと同様に、実行ユーザーが設定されているため、他ユーザーのプロセスを勝手に操作することはできない。
これはカーネルがひとつ一つのプロセスに「プロセスID」という一意の番号を割り振って、管理しているためである。

またLinuxの場合、プロセスが新しく作成されるときには、すでに存在している別のプロセスを元に作成される。
作成元のプロセスを親プロセス、作成されたプロセスを子プロセスと呼ぶ。
例えば、viコマンドを実行すると、シェルが親プロセス、viコマンドが子プロセスとなる。

プロセスの確認方法

psコマンドにて確認可能。

$ ps
// 現在のターミナルで実行しているプロセスを表示
$ ps xf
// 別のターミナルで実行しているコマンドや、デーモン(ターミナルに接続していないプロセス)を表示(macOSは$ ps -a)

ジョブについて

プロセスはカーネルから見た処理の単位であり、シェルから見た処理の単位を示す際には、「ジョブ」という言葉が使用される。
ジョブはコマンドラインに入力する一つの行を指す。
そのため、コマンドが一つだけの場合は、プロセスとジョブは同じ単位となる。
一方、パイプを使用した場合は、プロセスはコマンドごとになり、ジョブはコマンドライン全体でひとつとなる。

ジョブの制御

ジョブはcontrol + z コマンドで処理を一時停止することができる。
そのため、ジョブを切り替えて実行することができる。

$ vi test.js
// control + z コマンドでジョブを一時停止する

// コマンドプロンプトが表示されたらjobsコマンドで現在のジョブを確認
$ jobs
[1]  + suspended  vi test
// ジョブの一覧が表示される

// 再びジョブをフォアグラウンドにする(1はジョブナンバーを示す)
$ fg %1

// 重いファイルをコピーする
$ cp test1.js test2.js
// 処理中にcontrol + z コマンドでジョブを一時停止する

// バックグランドで先ほどの処理を実行する
$ bg %1
// 処理の間通常通りシェルを操作可能

// 切り替えず、バックグラウンドでそのまま実行する場合は& をコマンド末尾に付与する
$ cp test1.js test2.js &

// ジョブを停止する場合
$ vi test.js
// control + c コマンドでジョブを停止する

// killコマンドでも可能
$ jobs
[1]  + suspended  vi test
$ kill %1
// プロセスを終了する場合はプロセスIDを入力
$ kill プロセスID

ユーザーはシェルから操作することがほとんどのため、プロセスの制御よりもジョブの制御のほうが利便性が高い。

シグナルについて

シグナルとはプロセスに送信される信号のこと。
プロセスは受け取ったシグナルにより、終了・停止・再起動などさまざまな動作を示す。
つまり、さきほどのkillコマンドやcontrol + cなどのコマンドは元々はジョブ・プロセスを終了するコマンドではなく、シグナルを送るコマンドである。
killコマンドで送信するシグナルには番号がついており、デフォルトでTERM(Terminate)シグナルを送信する。シグナルは文字列意外にもシグナル番号で指定することができる。
以下はすべて同じコマンドとなる。

$ kill 1111
$ kill -TERM 1111
$ kill -15 1111

シグナルの一覧は下記のコマンドで確認できる。

$ kill -l