LPIC-1 - 101試験 - 103:GNUとUnixのコマンド - 103.5 プロセスを生成、監視、終了する

Last Update : September 18 2014 21:34:22

     

a. プロセスの管理

1.マルチタスク

Linuxカーネルはマルチタスクの仕組みを提供し、複数のプロセスを同時に実行可能です。ここで同時と書きましたが、ある一時点で処理を実行しているプロセス数は、そのシステムに搭載されているCPU数以上には決してなりません。他のプロセスは存在しますが、休止状態です。
Linuxカーネルは、複数のプロセスを短時間で切り替えながら動作させ、いかにも同時動作しているような環境を作り出しています。Linuxカーネルは、その時点で最も重要と思われるプロセスに実行権を与えるように動作します。このプロセスの動作の切り替えを行う機能のことをプロセススケジューラと呼びます。

限られた数のCPUを、数多くのプロセスから同時に利用するため、プロセススケジューラは最も動作させるにふさわしいプロセスにCPU実行権を与えようとします。最もふさわしいプロセスに実行権を与えるためには、もともとそのCPU上で動作していたプロセスの実行を中断し、新しいプロセスの実行を開始することになります。この処理のことを「プロセス切り替え」または、「プロセスディスパッチ」と呼びます。また、プロセス切り替えを行う機能を「プロセスディスパッチャ」と呼びます。

ところで、プロセスを切り替えるとは具体的にはどのような作業でしょうか。
あるCPU上で動作しているプロセスAから、別のプロセスBに切り替えることを考えてみましょう。

プロセスAは、プロセスAのために用意されたプロセス空間上で実行しています。プロセスAで実行中のプログラムでは、変数の値はメモリもしくはレジスタ上に存在し、実行中の命令はプログラムカウンタレジスタが指しています。プロセスAが利用中のスタックはスタックポインタが指しています。また、プロセスAのプロセス空間そのものも、特殊レジスタによって管理されています。

つまり、これらレジスタ群をすべてプロセスB用のレジスタ値で書き直せば、その瞬間からプロセスBが動作を始めることが理解できると思います。また、再度プロセスAの実行を再開できるようにするためには、プロセスB用のレジスタ値で書き直す前に、プロセスA用のレジスタ値を退避しておく必要があることも分かると思います。

これらレジスタ群の値のことをコンテキストと呼びます。実行待ち状態のプロセスは、これらコンテキストをtask_struct構造体やカーネルスタックに退避しておき、実際に実行状態になると、そのコンテキストをCPU上に読み込みます。

プログラムが動いている状態のことをプロセスと呼びます(タスクと呼ぶ場合もあります)。プロセスはどれも、システムのCPU時間やメモリ空間やディスク空間などのシステムリソースを使用しています。
Linuxではユーザーがプログラムを起動すると、その一つひとつが異なるプロセスとして動作します。プログラムが1つであっても、そのプログラムを実行しているプロセスが複数存在することもあります。
各プロセスは、そのプロセス固有のコンテキストをそれぞれ持ちます。コンテキストとは、そのプロセスが動作するためのプロセス空間、そのプロセスが動作するときのレジスタ値などです。これらの個々のプロセスに関する情報は、task_struct構造体(task_t型)で管理されています。Linuxカーネルがプロセスを操作するときは、この構造体を操作することになります。

すべてのプロセスにはプロセス ID (PID) と呼ばれる一意の値が割り当てられます。 この値はカーネルがユーザに実行状態の変化を報告するときにプロセスの身元を確認したり、 ユーザがシステムコールを実行するために参照する際に使用されます。

プロセスには必ず権限が関連付けられています。プロセスを開始したユーザーに関連付けられ、ユーザーから引き継がれたユーザーID(UID)とグループを表すグループID(GID)を持っています。これにより、プロセスがファイルシステムのどのオブジェクトにアクセスできるかを制限しています。プロセスは必ずプロセスを実行したユーザーの権限で実行されます。

新しいプロセスは、別のプロセスから起動されて実行します。元のプロセスを親プロセス、親プロセスから起動されるプロセスを子プロセスと呼びます。システムの起動時にカーネルによって最初に開始されるプロセスは、initというプログラムで、すべてのプロセスの最終的な親であり、initのPIDは1です。


b. プロセス間通信

基本的に、プロセスはお互いに干渉できないようになっています。それでは必要があっても、プロセス同士で情報を交換し合えないのでしょうか。そんなことはありません。プロセス同士が直接情報を交換することはできませんが、カーネルを通じて情報交換をする仕組みがあります。これらの仕組みを総称して、プロセス間通信(IPC=Inter Process Communication)といいます。

プロセス間通信の最も基本的なものが「シグナル」です。シグナルは一種の「命令信号」で、稼働中のプロセスに特定のシグナルを送信することで、あらかじめ決められた動作をさせることができます。

Linuxでは標準で表1のようなシグナルが利用できます。ただし、あるシグナルを受けた際の振る舞いはプロセスによっては異なる可能性があります。プロセスは、シグナルと動作の対応情報を個別にカーネルに登録できるようになっているからです*5。この登録情報をシグナル・ハンドラと呼びます。Linuxカーネルは、プロセスに対するシグナルを受信すると、まずシグナル・ハンドラが登録されているかを調べます。シグナル・ハンドラが登録されていればそこで指定される処理を実行し、登録されていなければデフォルトの動作を行います。
またシグナルは、プロセス同士で通信するだけでなく、カーネルからプロセスに情報を送るときにも利用します。


c. ジョブ管理

ジョブとは、ユーザーから見た実行中の処理の単位のことを言います。始めから終わりまでの一連の処理のことを言い、複数のプロセスから成り立っています。
ジョブにもジョブ番号と言う番号が振り分けられます。


1. フォアグランドジョブとバックグラウンドジョブ

ジョブには、フォアグランドジョブとバックグラウンドジョブがあります。
普通にシェルからコマンドを実行すると「フォアグラウンドジョブ」になります。
これは、その名の通り「前面」で実行されているプログラムをフォアグラウンドジョブ、「背面」(隠れて)実行されているプログラムをバックグラウンドジョブと言います。

● バックグラウンドジョブの実行構文
 [コマンド] &

$ gedit &

● フォアグラウンドジョブの実行構文
 [コマンド]

このフォアグラウンドジョブを終了するには「Ctrl」+「C」キーで強制終了させます。
一時停止(サスペンド)するには、「Ctrl」+「Z」キーを押します。


・フォアグラウンドジョブとバックグラウンドジョブを切り替える

● 一時停止をフォアグラウンドとして再開するには
 fg

● 一時停止をバックグラウンドとして再開するには
 bg

2. ログオフ後もジョブを続ける

nohup でコマンドを実行した場合は、ログアウトしてもプログラムを実行し続けます。長い処理を行っており、席を外したいときなどに使用すると便利です。ログアウトした後は、ジョブではなくプロセスとして管理することになります。また、処理中に出力されたメッセージは"nohup.out"に保存されます。

● nohup コマンド構文
 nohup コマンド [コマンドオプション]

● ログオフ後もジョブを続行する
$ nohup grep "sakura" access_log > result.txt &

3. ジョブの状況

ジョブの稼働状況を表示するには、 jobs コマンドを使います。。ジョブの状態は実行中がRunning、停止中が Stopped、終了がDoneとなります。また、状態の後に(tty output)や(tty input)と表示されているのは、それぞれ画面に文字を表示する直前と入力待ちを表します。フォアグラウンドになると実行を再開します。ジョブ番号の後に付いている記号は"+"がカレント・ジョブを表し、"-"が前のジョブを表します。

● jobs コマンド構文
 jobs [オプション] [ジョブID]

● jobs コマンドオプション
 -l プロセスIDも表示する
 -r 実行中のジョブだけを表示する
 -s 停止中のジョブだけを表示する

● ジョブの稼働状況を表示する
$ jobs
[1]-  停止                  top
[2]+  停止                  vi test2.txt


d. プロセス管理コマンド

1.コマンドをバックグラウンドで動作させる [ & ]

コマンドをバックグラウンドで動作させたい場合もあります。例えば、ハードディスク内 のファイルやディレクトリのインデックスデータベースを作成し、検索結果がすぐに返ってくるようにする場合、 updatedb コマンドは、フォアグラウンドで実行すると処理が終了するまでの間、ターミナルから他のコマンドを入力することができません。その間の時間はもったいないので、updatedb コマンドの後ろに & を付加し、updatedb コマンドの処理をバックグラウンドで動作するようにします。

# updatedb &

なお、updatedb コマンドをバックグラウンドで動作中に、jobs コマンドを実行すると、現在バックグラウンドで動作しているコマンドの確認を行う事ができるようになります。

# updatedb &
# jobs
[1]+ Running updatedb &


2.複数のコマンドを続けて実行する [ && ] [ || ] [ ; ]

複数のコマンドを続けて実行するには、コマンドとコマンドを && で繋げます。&& は、最初のコマンドが成功した場合のみ、2番目のコマンドを実行します。これは、ソースからインストールする場合などに、make が成功した場合に、make install を実行するという場合によく使われます。

# make && make install

逆に、最初のコマンドが失敗した場合のみ、2番目のコマンドを実行する場合は、|| で繋げます。

$ command || command

セミコロン「 ; 」を使用すると、一行のコマンド入力で複数のコマンドを実行できます。以下は、file5 の内容を表示した後、cd コマンドでカレントディレクトリを移動しています。

$ cat file5 ; cd /etc/rc.d/


3.指定したプロセスにシグナルを送信する [ kill ] [ killall ]

kill コマンドは、指定されたプロセスまたはジョブに対してシグナルを送って終了・再起動させます。シグナルとは、プロセスに送られるメッセージです。
シグナルを指定しない場合は、TERMシグナルが送られます。

● kill コマンド構文
 kill [-シグナル名または-シグナル番号] プロセスID

 kill -s [シグナル名またはシグナル番号] プロセスID

 kill -SIGシグナル名 プロセスID

● kill コマンドオプション
 シグナル名 シグナル番号 説明
 HUP 1 プロセスの再起動
設定ファイルの再読み込みを行います。
 INT 2 端末からの割り込み(CTRL+C と同じ)
割り込みにより動作が停止します
 QUIT 3 端末からcoreqダンプを作成して終了要求。(CTRL+\ と同じ)
 KILL 9 プロセスの強制終了要求
 TERM 15 プロセスの終了要求(デフォルト)正常終了します。
 CONT 18 中断状態のプロセスの再開を通知する。「バックグラウンドに回った」プロセスを再開する。
 STOP 19 プロセスの実行中断を通知する
 TSTP 20 プロセスを一時停止する。いわゆる「バックグラウンドに回す」である。サスペンド(CTRL+Z と同じ)

例えば、Apache を再起動させる場合を例にすると以下のようになります。

# ps aux | grep httpd
root 786 0.0 1.0 10788 2572 ? S Feb01 0:02 /usr/local/apache2/bin/httpd -k start
# kill -1 786

もしくは、

# kill HUP httpd

複数のプロセスに同時にシグナルを送る場合は、並べて記述します。

# kill -1 786 560

プロセスの名前でシグナルを送る場合は、 killall コマンドを使用します。

● killall コマンド構文
 killall [-シグナル名または-シグナル番号] プロセス名

 killall -s [シグナル名またはシグナル番号] プロセス名

 killall -SIGシグナル名 プロセス名

httpdなどは複数のプロセスが起動しているので、それらすべてを再起動するには

# ps -ax | grep httpd
2117 ? Ss 0:00 /usr/sbin/httpd 2138 ? S 0:00 /usr/sbin/httpd 2139 ? S 0:00 /usr/sbin/httpd 2141 ? S 0:00 /usr/sbin/httpd 2142 ? S 0:00 /usr/sbin/httpd 2143 ? S 0:00 /usr/sbin/httpd 2144 ? S 0:00 /usr/sbin/httpd 2145 ? S 0:00 /usr/sbin/httpd 2146 ? S 0:00 /usr/sbin/httpd 2147 ? S 0:00 /usr/sbin/httpd
# killall -s HUP httpd

4.メモリの使用状況を確認する [ free ]

メモリの使用状況を確認するには、 free コマンドを使用します。

# free -t
total used free shared buffers cached Mem: 255312 251636 3676 0 79152 123176 -/+ buffers/cache: 49308 206004 Swap: 265032 15608 249424 Total: 520344 267244 253100
# free -tm
total used free shared buffers cached Mem: 503 434 68 0 9 104 -/+ buffers/cache: 319 183 Swap: 258 0 258 Total: 762 434 327

残りの空きメモリ量は単純に free 項の68MBだけを見るのではなく、free+buffers+cashed(+swap)を加算した値になります。ここでは、物理メモリに 68+9+104=183MB残っており、さらに物理メモリが不足した際に仮想的にディスク領域をメモリに割り当てるswap を足すと計327MBのメモリが残っていることになります。


● free コマンド構文
 free [オプション]

● free コマンドオプション
 -t RAM と swap のトータルメモリを表示する
 -s 秒数 指定秒ごとにリアルタイムに更新して表示する
 -b -b でバイト、-k でキロバイト、-m でメガバイト、-g でギガバイト表示する


5.実行中のプロセスを表示する [ ps ]

実行中のプロセスを表示するには、 ps コマンドを使用します。

# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.0 2900 1428 ? Ss Apr06 0:00 /sbin/init root 2 0.0 0.0 0 0 ? S Apr06 0:00 [kthreadd] root 3 0.0 0.0 0 0 ? S Apr06 0:00 [migration/0] root 4 0.0 0.0 0 0 ? S Apr06 0:00 [ksoftirqd/0] root 5 0.0 0.0 0 0 ? S Apr06 0:00 [migration/0] root 6 0.0 0.0 0 0 ? S Apr06 0:00 [watchdog/0] ・ ・ 省略

● ps コマンド構文
 ps [オプション] [プロセスID]

● ps コマンドオプション
 a 全てのユーザーのプロセスを表示
 f プロセスをツリー形式で表示
 r 実行中のプロセス情報のみ表示
 u プロセスを実行しているユーザー名を同時に表示
  全ての制御端末のプロセスを表示(デーモンのように制御端末のないプロセスの情報も表示する)。
 -e 全てのプロセスを表示する
 -l 標準のPID、TTY、TIME、CMDに加え、F、S、UID、PPID、C、PRI、NI、ADDR、SZ、VSZ、RSS、WCHAN、STATも表示する
 -p PID 特定のPIDのプロセス情報のみ表示する
 -C プロセス名 指定した名前のプロセス情報のみ表示する
 -w 行を追加して表示する。wを複数書くとその数だけ行が増える

● ps フィールドの説明
 F プロセスの状態を示すフラグ。16進数で表されている。それぞれ、00:プロセスが終了している、01:システム・プロセス(常にメモリー上に存在する)、 02:親プロセスからトレースされている、04:親プロセスからトレースされ、停止している、08:プロセスがシグナルで起動できない、10:プロセスがメモリー上にあり、イベント終了までロックされている、20:プロセスがスワップできない、ことを意味している。
 UID プロセスを実行しているユーザーID
 PID
プロセスID
 PPID 現在のプロセスの親プロセスID
 PRI 優先度
 NI ナイス値(優先順位)
 VSZ 仮想メモリの全サイズ
 RSS 使用中の物理メモリー量
 WCHAN プロセスが休眠状態の時のカーネル関数名
 STAT/S プロセスのステータス。Rは実行可能、Sは停止、Dは割り込み不可の停止、Tは停止またはトレース中、Zはゾンビ・プロセス、Wはスワップ・アウトしたプロセス、Nはナイス値が正であることを表す
 TTY 制御端末の種類および番号。どの端末から起動されたか(?=端末以外からの起動)
 TIME プロセスが開始した時刻
 COMMAND/CMD プロセスのコマンド名



6.実行中のプロセスをツリー形式で表示する [ pstree ]

pstree コマンドは、プロセスの親子関係をテキストでツリー表示します。


$ pstree
init-+-NetworkManager
     |-abrt-dump-oops
     |-abrtd
     |-acpid
     |-atd
     |-automount---4*[{automount}]
     |-avahi-daemon---avahi-daemon
     |-bonobo-activati---{bonobo-activat}
     |-certmonger
     |-console-kit-dae---63*[{console-kit-da}]
     |-crond
     |-cupsd
     |-2*[dbus-daemon]
     |-dbus-launch
     |-devkit-power-da
     |-gconfd-2
     |-gdm-binary---gdm-simple-slav-+-Xorg
     |                              |-gdm-session-wor
     |                              |-gnome-session-+-at-spi-registry
     |                                              |-gdm-simple-gree
     |                                              |-gnome-power-man
     |                                              |-metacity
     |                                              |-polkit-gnome-au
     |                                              |-{gnome-session}
     |-gnome-settings----{gnome-settings}
     |-gvfsd
     |-hald---hald-runner-+-hald-addon-acpi
     |                    `-hald-addon-inpu
     |-httpd---9*[httpd]
     |-master-+-pickup
     |        `-qmgr
     |-5*[mingetty]
     |-modem-manager
     |-nmbd
     |-ntpd
     |-polkitd
     |-pulseaudio---2*[{pulseaudio}]
     |-rpc.idmapd
     |-rpc.statd
     |-rpcbind
     |-rsyslogd---3*[{rsyslogd}]
     |-rtkit-daemon---2*[{rtkit-daemon}]
     |-smbd---smbd
     |-sshd---sshd---bash---pstree
     |-udevd---2*[udevd]
     |-wpa_supplicant
     |-xinetd
              

● pstree コマンド構文
 pstree


7.プログラムのプロセスIDを調べる [ pidof ]

プログラムのプロセスIDを調べるには、 pidof コマンドを使用します。-s オプションをつけると、最も番号の大きいプロセス番号を表示します。

$ pidof httpd
705 701 663 657

● pidof コマンド構文
 pidof  [オプション] [サービス名]


8.特定のポートのプロセスを調べる [ lsof ]

lsof コマンドは、特定のポートをオープンしているプロセスを調べることができます。
オプションに「-i:ポート番号」「-i:サービス名」を指定します。

# lsof -i:imap
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME couriertc 3069 root 5u IPv6 12817 TCP *:imap (LISTEN)
# lsof -i:ssh
COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME sshd 2876 root 3u IPv6 6570 TCP *:ssh (LISTEN) sshd 4979 root 4u IPv6 177915 TCP 1.a.jp:ssh->2.a.jp:4008 (ESTABLISHED) sshd 4981 sakura 4u IPv6 177915 TCP 1.a.jp:ssh->2.a.jp:4008 (ESTABLISHED)

● lsof コマンド構文
 lsof  [オプション] [サービス名]


9.実行中のプロセスをリアルタイムに表示する [ top ]

top コマンドは、実行中のプロセスをリアルタイムに表示する事ができます。top コマンドを実行中は、操作ができなくなってしまうため、複数の仮想端末をたちあげながら実行するといいでしょう。

$ top
top - 16:29:34 up  3:03,  2 users,  load average: 0.04, 0.13, 0.07
Tasks: 184 total,   1 running, 183 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0%us,  0.2%sy,  0.0%ni, 99.8%id,  0.0%wa,  0.0%hi,  0.0%si,  0.0%st
Mem:   1937872k total,   577096k used,  1360776k free,    91720k buffers
Swap:  4161528k total,        0k used,  4161528k free,   270408k cached

  PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND
    1 root      20   0  2896 1412 1192 S  0.0  0.1   0:00.86 init
    2 root      20   0     0    0    0 S  0.0  0.0   0:00.00 kthreadd
    3 root      RT   0     0    0    0 S  0.0  0.0   0:00.09 migration/0
    4 root      20   0     0    0    0 S  0.0  0.0   3:40.03 ksoftirqd/0
    5 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/0
    6 root      RT   0     0    0    0 S  0.0  0.0   0:00.01 watchdog/0
    7 root      RT   0     0    0    0 S  0.0  0.0   0:00.06 migration/1
    8 root      RT   0     0    0    0 S  0.0  0.0   0:00.00 migration/1
    9 root      20   0     0    0    0 S  0.0  0.0   0:01.19 ksoftirqd/1
   10 root      RT   0     0    0    0 S  0.0  0.0   0:00.01 watchdog/1
   11 root      20   0     0    0    0 S  0.0  0.0   0:00.83 events/0
   12 root      20   0     0    0    0 S  0.0  0.0   0:00.17 events/1
   13 root      20   0     0    0    0 S  0.0  0.0   0:00.00 cgroup
   14 root      20   0     0    0    0 S  0.0  0.0   0:00.00 khelper
   15 root      20   0     0    0    0 S  0.0  0.0   0:00.00 netns
   16 root      20   0     0    0    0 S  0.0  0.0   0:00.00 async/mgr
   17 root      20   0     0    0    0 S  0.0  0.0   0:00.00 pm
              

top コマンド実行中は対話形式でコマンドを使用する事ができます。使用できるコマンドは以下表の通りです。


● top コマンド構文
 top [オプション]

● top コマンドオプション
 k プロセスに対してkill コマンドを実行
 q top コマンドを終了させる
 r プロセスの優先度を変更する
 s 表示が更新される間隔を秒単位で指定する
 M メモリ使用量の大きいプログラム順にソートする


z. 出題範囲概要

●説明 基本的なプロセス管理を行う。
●主要な知識範囲
ジョブをフォアグラウンドやバックグラウンドで実行する
ログアウト後にも実行が継続されるようにプログラムにシグナルを送信する
活動中のプロセスを監視する
プロセス群を選択し、並べ替えて表示する
プロセスにシグナルを送信する
●重要なファイル、用語、ユーティリティ
&, bg, fg, jobs, kill, nohup, ps, top, free, uptime, killall


  [ 例題 ] 
  1. 101:103.5 問01  topコマンド
  2. 101:103.5 問02  nohupコマンド
  3. 101:103.5 問03  プロセスの実行優先度
  4. 101:103.5 問04  nohupコマンド
  5. 101:103.5 問05  ログアウト後もコマンドの実行
  6. 101:103.5 問06  バックグラウンド
  7. 101:103.5 問07  フォアグラウンド
  8. 101:103.5 問08  psコマンド
  9. 101:103.5 問09  バックグラウンドの再開
  10. 101:103.5 問10  psコマンド
  11. 101:103.5 問11  updatedbコマンド
  12. 101:103.5 問12  プロセスの停止
  13. 101:103.5 問13  プロセスの強制終了
  14. 101:103.5 問14  優先度の変更
  15. 101:103.5 問15  プロセスの終了
  16. 101:103.5 問16  HUPシグナル
  17. 101:103.5 問17  バックグラウンド
  18. 101:103.5 問18  システム状況の監視
  19. 101:103.5 問19  ログオフ後もジョブを実行し続ける


     

www.it-shikaku.jp