Linuxオペレーティングシステムのプロセス(基本概念)

Linuxシステムの主なアクティブエンティティはプロセスです。 各プロセスは1つのプログラムを実行し、最初に1つの制御フローを受け取ります。 つまり、プロセスには、次の実行可能な命令を追跡する1つの命令カウンターがあります。 Linuxでは、プロセスが(実行を開始した後)追加のスレッドを作成できます。



Linuxはマルチタスクシステムであるため、複数の独立したプロセスを同時に実行できます。 さらに、各ユーザーは複数のアクティブなプロセスを同時に持つことができるため、大規模システムで数百、数千ものプロセスを同時に動作させることができます。 実際、ほとんどのシングルユーザーワークステーションでは(ユーザーがどこかに行ったとしても)、 デーモンと呼ばれる多数のバックグラウンドプロセスが動作します。 システムがシェルスクリプトから起動すると起動します。



典型的なデーモンはcronです。 彼は1分間に1回目を覚まし、何かをする必要があるかどうかを確認します。 彼が仕事をしているなら、彼はそれをやり、それからさらに眠りにつく(次のチェックまで)。



このデーモンにより、Linuxシステムを数分、数時間、数日、さらには数か月前から計画することができます。 たとえば、ユーザーが来週の火曜日の午後3時に軍事登録と入隊のオフィスに到着するようにスケジュールされているとします。 彼は、cronデーモンデータベースにエントリを作成して、たとえば14:30に通知することができます。 指定された日時が来ると、 cronデーモンは動作していることを確認し、指定された時間に(新しいプロセスとして)サウンドシグナルプログラムを開始します。



また、 cronデーモンは 、毎日午前4時にディスクバックアップを行うタスクや、毎年12月31日より前の週に忘れっぽいユーザーに新しい年を祝うためのギフトを購入するように促すタスクを定期的に実行するためにも使用されます 。 他のデーモンは、受信および送信電子メール、プリンターキューを管理し、まだ十分な空きページのメモリがあるかどうかを確認します。 デーモンはLinuxシステムに非常に簡単に実装されます。これは、デーモンはそれぞれ他のすべてのプロセスから独立した別個のプロセスであるためです。



Linuxオペレーティングシステムで作成されたプロセスは非常に単純です。 forkシステムコールは、 親プロセスと呼ばれる元のプロセスの正確なコピーを作成します 。 新しいプロセスは子プロセスと呼ばれます 。 親プロセスと子プロセスには、独自の(プライベート)メモリイメージがあります。 その後、親プロセスがその変数のいずれかを変更すると、これらの変更は子プロセスから見えなくなります(逆も同様です)。



開いているファイルは、親プロセスと子プロセスの間で共有されます。 これは、 forkシステムコールが行われる前に親プロセスでファイルが開かれた場合、将来は両方のプロセスで開かれたままになることを意味します。 いずれかのプロセスによってこのファイルに加えられた変更は、他のプロセスから見えるようになります。 これらの変更は、このファイルを開く他のプロセスにも表示されるため、この動作が唯一の妥当な動作です。



メモリイメージ、変数、レジスタ、およびその他すべてが親プロセスと子の間で同一であるという事実は、少し困難につながります。プロセスは、それらのどれが親コードを実行する必要があり、どれが子であるかをどのように知るのですか? その秘密は、forkシステムコールが子プロセスに0を返し、親が子プロセスのゼロ以外のPID(プロセスIDentifier)に戻ることです。 通常、両方のプロセスは戻り値をチェックし、それに応じて動作します。



pid = fork( ); /* fork , pid > 0 */

if (pid < 0) {

handle_error(); /* fork (, -

) */

} else if (pid > 0) {

/* */

} else {

/* */

}








子プロセスがそのPIDを知りたい場合は、 getpidシステムコールを使用できます。 プロセス識別子はさまざまな方法で使用されます。 たとえば、子プロセスが終了すると、その親は新しく終了した子プロセスのPIDを受け取ります。 親プロセスは多くの子プロセスを持つことができるため、これは重要です。 子プロセスには子プロセスも含めることができるため、元のプロセスは、子、孫、ひ孫、およびより遠い子孫のツリー全体を作成できます。



Linuxシステムでは、プロセスは何らかの形式のメッセージングを使用して相互に通信できます。 1つのプロセスがバイトストリームを書き込み、別のプロセスがそれを読み取ることができる2つのプロセス間にパイプを作成できます。 これらのチャンネルはパイプと呼ばれることもあります。 プロセスの同期は、空のチャネルからデータを読み取ろうとするときにプロセスをブロックすることで実現されます。 チャネルにデータが表示されると、プロセスのロックが解除されます。



チャンネルの助けを借りて、シェルコンベアが編成されます。 シェルが次のような行を見るとき

ソート<f |

次に、 sortheadの 2つのプロセスを作成し、さらに、ソートプログラムの標準出力ストリームがheadプログラムの標準入力ストリームに接続されるように、それらの間にチャネルを確立します。 この場合、 ソートが書き込むすべてのデータは直接ヘッドに送られ、一時ファイルは必要ありません。 チャネルがオーバーフローすると、システムは、 ヘッドが少なくとも一部のデータを削除するまでソートを一時停止します



プロセスは別の方法で通信することもできます-ソフトウェア割り込みを使用します。 1つのプロセスが別のいわゆるシグナルを送信できます。 プロセスは、シグナルが到着したときに実行するアクションをシステムに伝えることができます。 オプションは、シグナルを無視し、インターセプトし、シグナルにプロセスを強制終了させます(ほとんどのシグナルのデフォルトのアクション)。 プロセスが送信されたシグナルを傍受することを選択した場合、シグナル処理手順を示す必要があります。 シグナルが到着すると、制御は即座にハンドラーに転送されます。 信号処理手順が作業を完了すると、制御は信号が到着したときの場所に再び転送されます(これはハードウェアI / O割り込みの処理に似ています)。 プロセスは、直接の親(および他の祖先)、兄弟姉妹、および子(および他の子孫)で構成されるプロセスグループのメンバーにのみシグナルを送信できます。 プロセスは、1つのシステムコールでグループ全体にすぐにシグナルを送信することもできます。



信号は他の目的にも使用されます。 たとえば、プロセスが浮動小数点計算を実行し、誤って0で除算すると、SIGFPE信号を受け取ります(浮動小数点例外SIGnalは、浮動小数点演算を実行するときの例外信号です)。



All Articles