03. プロセスとジョブ
Photo by Standsome Worklifestyle on Unsplash
プロセスとジョブ, マルチタスクについて
GUI では直感的に理解できるマルチタスクも CUI ではその状態が見えにくい.
そこで,ユーザによるプロセスやジョブの制御を学ぼう.
まずプロセス制御とジョブ制御を明確に区別して学習し,理解してからそれらを使いこなすことを目的とする.
マルチタスクとは
同時に複数の処理をこなすこと,もしくはそれらの処理.
今や普通に触れる OS のほとんどはマルチタスクなシステムである.
プロセスとは
プロセス
一つのプログラムを良くみると様々な機能から構成されている.
そこで,こうした機能毎に動作を分離することで,様々な処理を能率良く,かつより分かりやすく安全に行なうことができる.
この時の,コンピュータ上で自立して動作する最小単位をプロセスと言う.
言い換えると,一つのプログラムは複数もしくは一つのプロセスからなる.
プロセスをさらに細分化した「スレッド」という概念もあるが
自立して動作しないものであり,ここでは触れない.
プロセス制御
unix 上ではほぼ常に多数のプロセスが(擬似的に)同時に動作している. この時,個々のプロセスを一時停止ないしは停止したり,優先順位を上下させたりすることができると何かと便利だ.
実際にそのようにプロセスの動作をその場で変えることをプロセス制御という.
プロセスの親子関係
unix では,全てのプロセスはなんらかのプロセスによって生成される.
これを「親子関係」と見なして,もとのプロセスを新しいプロセスの
「親プロセス」と呼ぶ.
「子プロセス」の「死体処理(ゾンビ状態のプロセスを消滅させること)」をするのは親プロセスの役目であるため,
子プロセスが親プロセスよりも先に死ななければいけない.
よって,何らかの理由により親プロセスが先に死んでしまった場合,
ゾンビになった子プロセスの処理が難しくなることがある.
プロセスの状態を知る. ps コマンド
プロセスの状態を知るには, ps コマンドを用いる. 詳細は以下のとおり.
- オプション無しだと「自分が実行した」プロセスのみが表示される.
- お勧めのオプションは,システム全体のプロセスがわかり,かつ, BSD でも linux でも cygwin でも有効な axu である.
ただし,cygwin システムはほとんどプロセスを持っていないため,ps axu
では寂しい結果しか表示されない. - cygwin では
ps -W
とすると,MS-Windows のプロセスも表示されるので,この方が良いかもしれない.
大学の情報教育システム, cygwin, 自分のPC上の仮想環境上の Unix等,なるべく多くの環境で ps axu
を試してみよう.
また、念のため、man ps
として、オンラインマニュアルを一瞥しておこう.
ps コマンドの使い方による違いの例
単に ps
とすると…
1 PID TTY TIME CMD
2 7229 pts/0 00:00:00 bash
3 7246 pts/0 00:00:00 ps
という感じで,「自アカウントで起動したプロセスしか見えない」が、ps axu
とすると
1USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2root 1 2.7 0.1 102800 12648 ? Ss 20:15 0:01 /sbin/init splash
3root 2 0.0 0.0 0 0 ? S 20:15 0:00 [kthreadd]
4root 3 0.0 0.0 0 0 ? I< 20:15 0:00 [rcu_gp]
5…略…
6osboxes 2469 0.0 0.0 172232 4896 ? Ssl 20:16 0:00 /usr/libexec/gvfsd-metadata
7osboxes 2515 9.7 0.8 677844 70280 ? Dsl 20:16 0:00 /usr/libexec/gnome-terminal-se
8osboxes 2541 0.0 0.0 20616 5168 pts/0 Ss 20:16 0:00 bash
9osboxes 2550 0.0 0.0 22176 1576 pts/0 R+ 20:16 0:00 ps axu
と表示され、「他人が動かしている」プロセス情報も見ることが出来る. なお上の結果は仮想環境 VirtualBox 上に OsBoxes からもってきた Ubuntu 23.10 を入れた環境のものだ.
ps コマンドで見られる情報のうち,重要なものだけ以下に解説しておこう.
情報名 | 内容 |
---|---|
USER | ユーザ名. そのプロセスの利用者. 注) 通常ユーザは,自分が利用しているプロセスしか制御できない. |
PID | プロセス ID. 各々のプロセスに固有な番号. プロセスの制御はこの PID を基本として行なわれる. |
%CPU | cpu 利用率. |
%MEM | メモリ使用率. |
tty | 制御端末名. そのプロセスがどの「端末」に属しているかを示す. |
STAT | プロセスの状態. トラブル時に役に立つ! 表示文字の意味は以下の通り(主要なもの). ''S'' … プロセスは sleep 状態(キーボード入力完了待ち)である. ''R'' … プロセスは実行可能状態. ''D'' … プロセスはディスク入出力完了待ちである. ''T'' … プロセスは停止(stop)中である. ''Z'' … プロセスはゾンビ(zombie, "死んでいる")である. T や Z という状態は異常事態を示唆する. また,長時間 D のままという場合も,何かおかしい可能性が高い. |
command | コマンド名と引数 |
ps
コマンドを用いて,今自分が実行している複数のプロセス全てについて,その状態がどうなっているかきちんと調べよ.
プロセスの状態を知る. top コマンド
プロセスの状態を知るには, top コマンドも使える.詳細は以下のとおり.
top
コマンドで,プロセスの状態を「動的」かつ「連続的」にみることができる.- 通常は,CPU利用率の高い順にプロセスが動的に並べ替えられて表示される.
- この「並べ替えに使う項目」は、
top
実行中に F キーを押せば変えることが出来る.
top
コマンドを実行し,挙動を見てみる.また,実行中に ? キーを押し,実行中に何ができるか把握せよ.
プロセスを制御: プロセスを作る,動作させる
ユーザから見たとき,プログラムを実行することは即ちプロセスを生成することである.
逆に,プログラムの実行が完全に終わったときには, そのプログラムによって作られたプロセスは全て消滅したことになる.
プロセスを制御: プロセスの優先度を変更する
プロセスには優先順位があり,優先順位が高い方がより先に実行されるようになっている. この仕組みにより,様々なプロセスが同時に動作しても人間にとって快適に扱えるようになっている.
優先順位を示す指標
語 | 意味 |
---|---|
スケジューリング優先度 | 0 〜 127 の数字で,小さい方が優先される. |
nice 値 | この数字とプロセスの性格などから, 上の優先度が決定される. -20 〜 20 程度の数字で,小さい方が優先される.デフォルトは 0. |
プロセスの優先順位を知る. ps -l (ps ハイフン エル) コマンド
プロセスの優先度と nice 値を見るには,
ps -l (← ps に対し、ハイフンと小文字のL(エル)をオプションとして与えている)
とするのが簡単である.
表示カラムのうち,"PRI" が優先度(Priority), "NI" が nice値 である.
優先順位を変更する
プロセスの優先順位を変える. nice/renice コマンド
プロセスの優先順位を変えることも出来る. 重いプログラムを走らせる時などは、この操作を知っていると助かることも多い. 詳細は以下のとおり.
コマンド | 解説 |
---|---|
nice |
プログラム起動時に nice 値を決定するコマンド. デフォルトでは 10 だけ nice値を上げる(= 優先度を下げる). 通常ユーザは優先度を低くすることしか出来ないが、 管理者は優先度を上げることも出来る. 注) csh 系のシェルに nice コマンドが組み込まれていることがある. システムの nice コマンド( /bin/nice )とかぶるので混同しやすい. 事前にマニュアルを見るなどして、気をつけよう. |
renice |
既に動いているプロセスの nice 値を変更するコマンド. 通常ユーザの制限は nice と同様. |
使い方の例 (詳しくはマニュアルを見よう)
nice
については、基本は nice 起動したいコマンド
とするだけである.
例えば、
hoge というプログラムを, 通常より nice 値を 10 大きくして(= 優先順位が下がる)起動するときは
1/bin/nice hoge
とすればよい.
既に起動しているプログラムがあるとして、その nice 値を変える例も見てみよう.
まず、そのプロセスの PID と nice 値を ps -l
コマンドを使って確認してみる.
1$ ps -l
2F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
30 S 1000 2848 2515 0 80 0 - 5154 do_wai pts/2 00:00:00 bash
40 S 1000 3501 2848 3 80 0 - 155273 do_sel pts/2 00:00:00 emacs
50 R 1000 3523 2848 0 80 0 - 5544 - pts/2 00:00:00 ps
と表示されるので、
例えばそのプログラムが emacs だとすると、PID は 3501, nice 値は 0 ということが分かる.
renice
コマンドは、renice nice値 PID
という形で用いるので、
1renice +10 3501
とすると、
13501 (process ID) 従来の優先順位は 0 で, 新しい優先順位は 10 です
と表示が出て、優先度が変更されたとメッセージが出る(優先順位が下がるので、日本語としては誤解を招くメッセージだが!).
実際に、ps -l
コマンドで確認してみると、
1$ ps -l
2F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
30 S 1000 2848 2515 0 80 0 - 5154 do_wai pts/2 00:00:00 bash
40 S 1000 3501 2848 0 90 10 - 155273 do_sel pts/2 00:00:00 emacs
50 R 1000 3539 2848 0 80 0 - 5544 - pts/2 00:00:00 ps
emacs の priority値と nice値 が確かに 10 だけ大きくなっている.
試しに、優先順位を上げようとして
1renice -10 3501
とすると、
1renice: 3501 (process ID) の優先順位の設定に失敗しました: 許可がありません
と言われて、優先順位を上げることが出来ないことも確認できる.
プロセスを終了させる. kill コマンド
プロセスを停止させるには kill コマンドを使う.詳細は以下のとおり.
unix のプロセスには「プロセス間通信」といってプロセス同士が通信する仕組みが備わっている.
このプロセス間通信のうち,メッセージを伝えるだけの機能を持つものとして「シグナル」がある.
このシグナルをプロセス宛に送りつけることによって,プロセスを一時停止させたり,再起動させたり,終了させたりできる.
シグナルをプロセスに送りつけるには,
1kill -シグナル pid
とする.
シグナルは次の表の「シグナル名」か「シグナル番号」で指定する.
なお、シグナルを省略すると TERM (=15) を指定したことになる.
シグナル番号 | シグナル名 | シグナルの意味 |
---|---|---|
15 | TERM | TERMinate. 終了. ''kill'' コマンドのデフォルト. |
9 | KILL | KILL. 「強制」終了. このシグナルを受け取ったプロセスは終了することになっている. |
2 | INT | INTerrupt. 端末から割り込み(''CTRL-c'')を受けた,という意味. このシグナルを受けたプロセスは終了する. |
3 | QUIT | QUIT. 端末から中断終了(''CTRL-'')を受けた,という意味. このシグナルを受けるとプロセスは(core を吐いて)死ぬ. |
18 | TSTP | TerminalSToP. 端末から停止(''CTRL-z'')を受けた,という意味. このシグナルを受けるとプロセスは一時停止する. |
17 | STOP | STOP. 強制一時停止. このシグナルを受けるとプロセスは一時停止する. |
19 | CONT | CONTinue. 停止状態のプロセスの実行を再開する. |
1 | HUP | HangUP. 端末回線が切れた,ということを意味する. 普通のプロセスはこのシグナルを受けると実行を中止するが, 再起動したり特別なモードに移行するプロセスも多いので注意が必要. |
この表から分かるように,そのプロセスを確実に止めたい場合は,
1kill -9 pid
とするか,
1kill -KILL pid
とすればよい.
シグナル "HUP" や pid "1" "0" "-1" は特別な意味で使われることが多いので,よくわからない場合は使わないように注意すること.
酷い目にあってみたい,という酔狂な人は自宅の unix などでスーパーユーザになって,
kill 1
kill -KILL -1
などといろいろやってみよう(^-^).
state が D のプロセスや,zombie プロセスには kill -KILL
が有効でない場合がある.
こういう場合は,特に支障がなければ放置しておくことになるが(^-^)、まあ、様子を見て、支障がありそうだったら管理者に相談しよう.
カーネギーメロン大学卒,MIT で修士号,スタンフォード大学で博士号をとって今は Google 勤めの Dan Maynes-Aminzade による ラップ曲 Kill -9 というのがある.ああ~,と生暖かい目で一度見ておくといいだろう.
接続が切れたことを無視させる. nohup コマンド
ユーザがログアウトしても動き続けるようにプログラムを起動することが出来る.
プログラムが動作中であっても,端末を終了したりログアウトしたりすると通常はそのプログラムは終了してしまう.
これは,そのプログラムを起動した端末環境が,終了する直前にそのプログラムに対して上の
''HUP''
シグナルを送っているためである.
しかし,長時間の計算をするときなど,
「ログアウトした後もプログラムは動きつづけたままでいて欲しい」
ということがある.
こうしたときには, nohup
コマンドを用いて nohup コマンド名
としてプログラムを起動すると,ログアウトしてもこのプログラムが動作し続けるようにできる.
コマンド指定無しで単に nohup
と起動しないこと!
こうしまうと,それ以降のコマンド全てが nohup 扱いになり,ログアウトしても起動したプログラムの動作が止まらない.大きなトラブルを引き起こす可能性が高いので,留意すること!
次の手順でプロセス制御を試してみよう.
- 端末エミュレータ中で
emacs -nw
と入力して emacs を起動する.
ただし,emacs がデフォルトでインストールされていない Ubuntu などの場合はインストールしてからこの作業をやろう. インストール方法は脚注1を見よう. - emacs が起動している状態で
CTRL-z
として,emacs を停止状態にする(CTRL-z
や停止状態の説明は後述). ps
コマンドを試してみて,emacs の存在とその状態を把握する.top
コマンドを試してみて,emacs の存在とその状態を把握する.ps
コマンドで emacs の PID を把握し,kill
コマンドを用いて emacs を強制終了させる.ps
コマンドで emacs が存在しない(強制終了したため)ことを確認する.
ジョブ
ジョブとは,(シェルから見た)コンピュータ上で実行される実態の単位の概念で,
「一連の仕事をしている(複数の)プロセス」
のことである.
まあ簡単に言えば,シェルで命令した「(一行分の)命令の固まり」であり,
人間にとって一つの処理と見なせるもの,と思えばよい.
シェルの history コマンドで「一回分」のコマンドと思ってもよい.
フォアグラウンド,バックグラウンド
シェルは人間と「対話的」に動作するため,そのまま複数のプログラムを同時に動作させるわけにはいかない.
そこで,「人間と対話しながら作業するジョブを一つだけ」と 「そうでないジョブ(複数)」 をわけることでマルチタスクを可能としている.
その全体の関係は下の図のようになっている.

ジョブ状態 | 説明 |
---|---|
フォアグラウンド | シェルを通じて人間からのキーボード入力を受けるジョブの状態. つまり,通常使っている状態のジョブはフォアグラウンドにいるのである. 端末1つにキーボードは1つしかないので,フォアグラウンドジョブは端末1つにつき,1つしか存在できない. |
バックグラウンド | キーボードと関係なく、背後で動作している状態. この状態で動作するジョブはいくつあってもよい. |
停止状態 | 起動はしているが,一時停止している状態. ジョブをバックグラウンドへ持っていくときの途中状態としても用いる. |
ジョブの状態を知る. jobs コマンド
ジョブの状態を知るには, jobs コマンドを用いる. 詳細は以下のとおり.
例えば、三つほど一時停止 or 裏で動いているジョブがある状態で、jobs
とすると、次のような出力を得られる.
1osboxes@osboxes:~$ jobs
2[1]- 停止 emacs -nw
3[2] 実行中 sleep 1000 &
4[3]+ 停止 man less
この表示は左から,
''ジョブ番号 状態 コマンドと引数''
というリストになっている.
ジョブ番号に「+」がついているのは,ジョブ操作コマンドのデフォルトの対象がこれであることを意味している.
(だいたいは一番大きい番号だ)
ちなみに,この例では二つのジョブが「中断」状態,つまり「停止状態」で, 一つが「実行中」、つまりバックグラウンドに居ることがわかる.
端末エミュレータ中で emacs -nw &
や sleep 1000 &
などを何度か入力するなどして, jobs
コマンドの様子を試してみよ.
ジョブ制御
ジョブ制御とは,ジョブを三状態のある状態から他の状態へと移動させることや, プロセス制御と同じくジョブを「殺したり」することを言う.
ジョブには大まかにいって上に載せた図のような三つの状態がある. 図中にあるようなコマンドを用いてジョブの状態を変遷させることが ジョブ制御の中心となる. 詳細は以下の通り.
ジョブ制御: ジョブを作る
& をつけて起動するとそのジョブはバックグラウンド状態に
並列でジョブを走らせるとか Window 環境で「別窓」を開きたい時はこうする
シェルを通じてプログラムを実行したとき,
シェルに投入された一塊のコマンド(群)がジョブとして生成される.
この時, 起動オプションとして &
をつけるかどうかで、ジョブの状態が次のように変わる.
&
をつけない → そのジョブはフォアグラウンド状態で起動する.
&
をつける → そのジョブはバックグラウンド状態で起動する.
window system が動作しているときに 端末中で ''emacs &'' とすると,emacs が「別窓で」起動するのが見られるが,これがそうである.
ジョブ制御: ジョブの状態を変える
以下、ジョブ制御のコマンドを紹介しよう.
なお、ジョブを フォアからバックに直接移す方法は無い.
フォア → 停止 → バック と経由する方法( CTRL-z
→ bg %ジョブ番号
というコンボ)があるのでそちらを使おう.
バック/停止 ジョブをフォアへ. fg コマンド
バックグラウンドで動いている or 停止しているジョブと「対話」するにはフォアへ持ってくる
fg
コマンドで fg %ジョブ番号
とすると、そのジョブ番号をもつジョブをフォアグラウンドへ移すことができる.
これでキーボードでそのジョブと対話が可能になる.
フォアに居るジョブを停止. CTRL-z キー
今「対話」しているするジョブを停止するには CTRL-z キーを使う.
ただし,シェルそのものだけはこれで停止しないようになっている(例外).
シェルを停止したい場合は, suspend
コマンドを使う.
ジョブを バック ←→ 停止 の間を行き来させる. bg, stop コマンド
以下のようにして見えてないジョブを、動かしたり停めたり出来る
コマンド | 説明 |
---|---|
bg %ジョブ番号 |
そのジョブ番号をもつジョブをバックグラウンドに移す(動作させる) |
stop %ジョブ番号 (stop コマンドを内蔵するシェルの場合)kill -STOP %ジョブ番号 (そうでないシェルの場合) |
そのジョブ番号をもつジョブを停止状態にする(一時停止) |
近年、システムに上のものとは役割が異なる stop コマンドが実装されていることがあり、そういうシステムでは一部のシェルに stop コマンドが内蔵されていなかったりする.
stop コマンドを試してみて unknown job というエラーが出る場合はこれに該当するので、kill -STOP %ジョブ番号
を使おう.
ジョブを殺す. kill コマンド
ジョブ単位でも kill コマンドが使える
jobs
コマンドでわかるジョブ番号を用いて、
kill %ジョブ番号
とすればそのジョブを殺す(一時停止ではない、完全な停止)ことができる.
以前示したように、フォアグラウンドジョブ,即ち,人間と対話しながら動作しているジョブは
CTRL-c
などでも殺すことができる.
ただし,シェルそのものだけはこれで死なないようになっている(例外).
次の手順でジョブ制御を試してみよう.
touch
コマンドを用いてファイルを新しく作る.- 作ったファイルを 端末中で vi か emacs で編集し(''ジョブの投入''),適当に数行書き込む.
- vi or emacs を終了せずに,停止させることでシェルへ戻る(''ジョブの停止'').
less
コマンドを用いて編集したファイルを見る(''ジョブの投入 & 停止'').date
コマンドを用いて日時を調べて…(''ジョブの投入 & 停止'').fg
コマンドを用いて vi or emacs へ戻り(''停止ジョブをフォアグラウンドへ'')- 先ほど調べた日時を書き込んでから, vi or emacs を終了(''ジョブの停止'').
- 再び,
less
コマンドを用いて編集したファイルを見て,先ほどの日時書き込みが保存されていることを確認(''ジョブの投入 & 停止'').
レポート No.3
以下の課題について,なるべく一生懸命な調査と考察を行って,
学籍番号-氏名-03.pdf
というファイルとしてレポートを作成し、
webフォーム
から教官宛に提出しよう.
なお,レポートを $\TeX$ 等で作成したものを印刷した「紙媒体」を教官に直接手渡す形で提出してもよいが、物質によるレポート提出は常に破損や紛失の可能性があるのであまりお勧めはしないぞ.
注意
近年はセキュリティ上の懸念から,実行形式のプログラムなどをメールに添付するとそのメールそのものの受信を受信側サーバが拒絶したりする.
そういうことを避けるため,レポートをファイルで提出するときはそういった懸念のあるファイル形式のものではないようにしよう.
まあ要するに,レポートは pdf ファイルにして送るのが良い ということだと思っておこう.
- 本資料の実習部分をすべて行い,それについて「きちんと」報告せよ(やりました,などだけというのはダメだよね).
- ジョブを投入して停止状態にする方法を複数述べよ.
また,これらの作業を実際にやってみよ. なお,この操作の様子をscript
コマンドで記録しておいて,その記録を提出する形で報告すること.
script
コマンドはとても便利! なので、マニュアルなどでぜひ調べよう. kill
でもプロセスが殺せない場合が何通りか考えられる. そのうち,3種類を挙げてきちんと解説せよ.- ジョブを あわせて 5つほど投入し,全てが共存する状態にし,三状態を自在に遷移させてみよう.
なお,この操作の様子をscript
コマンドで記録しておいて,その記録を提出する形で報告すること.
-
emacs をインストールするには,たとえば Ubuntu の場合は端末ソフトウェア上で "sudo apt install emacs" とコマンドを打てば良い.パスワードを要求されたらきちんと入れよう.なおこの途中に "メールサーバソフト postfix の設定はどうする?" という選択肢が出ることがある.これは emacs がメールを読み書きできる機能を持つことから「ついでに postfix をインストールする?」ということで尋ねてきているのだ.通常は特に不要だろうから,"unchanged" を選べば良い. ↩︎