差分

移動先: 案内検索

プロセス管理

1,539 バイト追加, 2019年3月12日 (火) 23:29
/* 基本的なスケジューリング方式 */
プログラムが動作する実行実体のことをプロセスと呼びます。
単純化して説明すると、プログラムの実行のことです。
 
プロセスはプロセスごとにプロセスIDを付与され、その数字で管理されています。
このプロセスIDの数字は[[プロセスIDを擬似乱数生成関数の初期化パラメータに使う是非 | 一定の数字で循環]]します。
Linuxカーネルが扱えるプロセスIDの最大値は/proc/sys/kernel/pid_maxを参照すればわかりますが、
一般向けのLinuxディストリビューションであれば現状ではプロセスIDの最大値は 2^15 (32768) となっています。
 
 
それで説明が終わるのはあんまりなので、もうちょっと概念的にどのような位置づけなのか考えてみます。
スレッドやタスクの考え方(と、実装)は80年代にUNIXに入って来た、UNIXの歴史から見ると、わりと新しい技術です。
80年代に入ってから色々な組織がスレッドの実装を試みました。
Brown Univ米ブラウン大学の [https://cs.のブラウンスレッド、brown.edu/research/pubs/techreports/reports/CS-96-18.html Brown Thread Package (BTP)]、サンマイクロシステムズのLWP (Lightweiht ProcessLight-weight process)、DECのCMA スレッド、、DECのDECthreads、
CMUのCスレッドパッケージがありました。各々互換性はありません。
紆余曲折あり、現在ではPOSIX仕様のスレッドである[http://man7.org/linux/man-pages/man7/pthreads.7.html pthreads(7)]が主流になっています。
ですから、単純にプロセスと呼んでも構わないですし、
また同時に(ここまでの説明の範囲では)「プロセス=タスクのこと」と考えてもかまいません。
タスクは複数のスレッドを持つことができます。複数のスレッドが動き出すまでは、プロセスといってもいいわけですが、スレッドを複数持つ状態の場合は、プロセスと呼ぶよりタスクと呼ぶ方が適切でしょう。タスクは複数のスレッドを持つことができます。複数のスレッドが動き出すまでは、プロセスといってもいいわけですが、スレッドを複数持つ状態の場合は、プロセスと呼ぶよりタスクと呼ぶ方が適切でしょう。
このあたりは新旧の考え方が入り乱れて呼び方が混乱しているのは確かなようです。
UNIXが生まれた当時の処理の粒度と今時のUNIXでの処理の粒度は違うので、
;調べてみよう: コマンドuptimeのマニュアルを調べてみよう。またロードアベレージの意味も調べてみよう。コマンド[http://man7.org/linux/man-pages/man1/uptime.1.html uptime]のマニュアルを調べてみよう。またロードアベレージの意味も調べてみよう。
=== プロセスの状態 ===
==== 基本的なスケジューリング方式 ====
スケジューリングの方式にはポリシーと呼ばれる、いくつかの方式があります。スケジューリングの方式にはポリシーと呼ばれる、いくつかの方式<ref>Linux カーネル version 3.14 以降ではデッドラインスケジューリングポリシー (SCHED_DEADLINE) が追加されています。</ref>があります。
ラウンドロビンは一定時間CPU時間を消化したプロセスを待ち状態に戻し、待っていた次のプロセスに切替えて順繰りにプロセスを実行していく方法です。この一定時間のことをタイムスライス(timesliceTime Slice)といいます。公平にプロセスにCPUを割り当てることになります。タイムスライスを小さくすれば小さくするのど、細かくプロセスをCPUへ割り当てることができますが、しかし割り当て処理の回数が増えるにつれカーネル自体が消費するCPU時間も多くなっていきます。ですから、リーズナブルな値にしなければなりません。あるいはタイムクアンタム (Time Quantum)と呼びます。公平にプロセスにCPUを割り当てることになります。タイムスライスを小さくすれば小さくするのど、細かくプロセスをCPUへ割り当てることができますが、しかし割り当て処理の回数が増えるにつれカーネル自体が消費するCPU時間も多くなっていきます。ですから、リーズナブルな値にしなければなりません。
その後 Linux 3.14 (2014/3/20リリース) からリアルタイム指向の処理に必要なデットラインを処理するための [https://core.ac.uk/download/pdf/14699805.pdf SCHED_DEADLINE] がスケジューラ <ref> デフォルトで使えるかどうかはディストリビューションによります。</ref> に加わっています。Linux 3.14ではデットライン・スケジューラのアルゴリズムはEarliest Deadline First (EDF)を採用していましたが、Linux 4.13 (2017/9/5リリース)からはEDFを改良しさらに Constant Bandwidth Server ( CBS ) 加えた ( と、 [https://uc2.h2np.net/src/deadline_c.html#N1 ( と、カーネルのコメントでは表現している )カーネルのコメント] アルゴリズムを採用しています。では表現している )アルゴリズムを採用しています。
SCHED_IDLE min/max priority : 0/0
</pre>
 
 
タイムスライスの値はスケジューリングのポリシーによっても変化しますし、スケジューリング・ポリシーによっては動的にも変化します。
指定されたプロセスの SCHED_RR 間隔を取得するシステムコール[http://man7.org/linux/man-pages/man2/sched_rr_get_interval.2.html sched_rr_get_interval(2)]を使うと実際の[[プロセスのタイムスライスの値を計測する]]ことが可能です。
==== CFS ====
スレッドは計算資源を共有しCPU資源だけは別の状態であるような処理の流れをいいます。スレッドにはclone(2)のようなカーネルレベルで実行するスレッドとglibcなどユーザライブラリに含まれているユーザレベルで実行するスレッドの2つがあります。ですからスレッドが必ずしもカーネルモードで動作しているわけではなく、それはプログラムの書かれ方によります。ここの説明ではカーネルスレッドとユーザスレッドとの両方取り上げてみます。
 
 
既に説明した通りfork(2)が親と子のプロセスで内容をコピーしているのですが、とはいえ fork(2) 後は各々の実体は独立しています。しかし、スレッドは内容が一緒ですから、つまり処理の流れを別に持つCPU資源だけは複数個持つのですから、新しいプロセスが生まれていないので親も子もありません。CPU資源以外の計算資源のコピーが必要ない場合、あるいは同じ計算資源でCPU 資源を複数持ちたい時、計算資源を共有したい時などにスレッドは便利です。
 
 
CPUリソースだけを同時に複数個持つことができることで、たとえば実行しているタスク中でネットワーク入出力からの処理を行いつつ同時に他の計算を繰り返すような場合に非常に有効に働きができます。
この利点は、資源コピーが発生しないまま処理スレッドだけを高速に立ち上げることができると説明しましたが実際にfork(2)とLinuxのpthreadライブラリ(カーネルスレッドではなくユーザスレッド)を使ってどれぐらい違うか試してみました。
1000 回プロセスを生成するのとスレッドを生成するプログラムを書いてみます。結果はAthlon 1GHzマシンでスレッド生成側がトータル0.157秒、プロセス生成側が0.360秒と2倍以上の差をつけました。このようにCPUリソースのみだけで処理が出来るようなものを大量に生成するような場合はスレッドが有利に働きます。
 
 
生成可能な最大スレッド数は利用しているシステムのメモリ量に依存します。/proc/sys/kernel/threads-max を参照することでわかります。
* fork版