ホームページ  >  記事  >  バックエンド開発  >  PHP スクリプトを使用してデーモン プログラムを作成する_PHP チュートリアル

PHP スクリプトを使用してデーモン プログラムを作成する_PHP チュートリアル

WBOY
WBOYオリジナル
2016-07-21 14:58:31769ブラウズ

デーモンプロセスとは

これも興味深い概念です。デーモンは英語で「エルフ」を意味し、漫画の主人公の周りを回って回ることがよくあります。時には長々としたアドバイスをくれたり、運悪く柱にぶつかったりすることもあります。そのため、デーモンは「守護神」と訳されることもあります。そのため、中国でもデーモンプロセスには「エルフプロセス」と訳す人もいますし、「デーモンプロセス」と訳す人もいます。

本物のデーモンと同様に、デーモン プロセスも人々の目から隠れて、静かにシステムに貢献することに慣れており、人々はそれらを「バックグラウンド サービス プロセス」と呼ぶこともあります。一般に、デーモン プロセスの存続期間は非常に長く、実行された瞬間からシステム全体がシャットダウンされるまで終了しません。有名な Apache や wu-FTP を含むほとんどすべてのサーバー プログラムは、デーモン プロセスの形式で実装されています。 Linux での inetd や ftpd などの多くの一般的なコマンドでは、末尾の文字 d はデーモンを指します。

なぜデーモンプロセスを使用する必要があるのでしょうか? Linux のすべてのシステムがユーザーと通信するインターフェイスはターミナルと呼ばれ、このターミナルから実行を開始するすべてのプロセスは、これらのプロセスのコントロールと呼ばれます。ターミナル(制御端末)、制御端末が閉じられると、対応するプロセスが自動的に閉じられます。この点に関しては、読者は X-Window の XTerm を使って試すことができます (各 XTerm はオープン ターミナルです)。次のようなコマンドを入力してアプリケーションを起動できます。 $netscape 次に、XTerm ウィンドウと起動したばかりの Netscape を閉じます。窓も一緒に突然蒸発してしまいます。ただし、デーモンプロセスは、対応するターミナルが閉じられている場合でも、ユーザーの影響を受けずにシステム内に長時間存在することができます。ターミナルまたはその他の変更が影響を受ける場合は、このプロセスをデーモン プロセスに変える必要があります。

デーモンプロセスのプログラミングルール

プロセスをデーモンプロセスに変えたい場合は、次の手順に厳密に従う必要があります:

1. fork を呼び出して子プロセスを生成し、同時に親プロセスを終了します。その後の作業はすべて子プロセスで行われます。これにより、次のことが可能になります:

1.1 コマンドラインからプログラムを実行すると、プログラムが実行されたかのような錯覚が生じ、シェルは戻って次のコマンドを待ちます。

1.2 フォークを通じて生成されたばかりの新しいプロセスは、プロセス グループのリーダーには絶対にならないため、ステップ 2 の実行の前提条件が保証されます。

これを行うと、非常に興味深い現象が発生します。親プロセスが子プロセスよりも前に終了しているため、子プロセスには親プロセスがなく、孤立プロセス (孤立) になります。システムが孤立プロセスを見つけると、そのプロセスは自動的にプロセス 1 に採用されます。このようにして、元の子プロセスはプロセス 1 の子プロセスになります。

2. setid システムコールを呼び出します。これはプロセス全体の中で最も重要なステップです。 setsid の概要については、付録 2 を参照してください。setsid の機能は、新しいセッションを作成し、セッション リーダーとして機能することです。呼び出しプロセスがプロセス グループのリーダーである場合、呼び出しは失敗しますが、これは手順 1 で保証されています。 setid の呼び出しには 3 つの機能があります:

2.1 プロセスに元のセッションの制御を削除させます;

2.2 プロセスに元のプロセス グループの制御を解除させます;

2.3 プロセスから元の制御端末の制御を取り除きます;

簡単に言うと、呼び出しプロセスを完全に独立させ、他のすべてのプロセスの制御の対象外にすることです。

3. 現在の作業ディレクトリをルート ディレクトリに切り替えます。

このプロセスを /mnt/floppy/ などの一時的にロードされたファイル システム上で実行すると、プロセスの現在の作業ディレクトリは /mnt/floppy/ になります。このファイルシステムを使用しているかどうかにかかわらず、プロセス全体でファイルシステムをアンマウント(umount)することはできず、これは非常に不便です。解決策は、chdir システム コールを使用して現在の作業ディレクトリをルート ディレクトリに変更することです。ルート ディレクトリを削除したい人はいないでしょう。

chdirの使用方法については、付録1を参照してください。

もちろん、このステップでは、特別な必要がある場合、現在の作業ディレクトリを別のパス (/tmp など) に変更することもできます。

4. ファイル許可マスクを 0 に設定します。

これにはシステムコール umask を呼び出す必要があります。付録 3 を参照してください。各プロセスは、親プロセスからファイル許可マスクを継承します。新しいファイルが作成されると、このマスクはファイルのデフォルトのアクセス許可を設定し、一般ユーザーの書き込み許可などの特定の許可をブロックするために使用されます。別のプロセスが exec を使用して、私たちが作成したデーモン プログラムを呼び出すと、そのプロセスのファイル許可マスクが何であるかがわからないため、新しいファイルを作成するときに何らかの問題が発生します。したがって、ファイル許可マスクをリセットする必要があります。これは任意の値に設定できますが、一般的には、ユーザー操作がブロックされないように、誰もがそれを 0 に設定します。

アプリケーションに新しいファイルの作成やファイル アクセス許可の設定がまったく含まれていない場合は、ファイル許可マスクを完全に開始して、この手順をスキップできます。

5. 不要なファイルをすべて閉じます。

ファイル許可マスクと同様に、新しいプロセスは親プロセスから開いているファイルの一部を継承します。これらの開かれたファイルは、デーモン プロセスによって読み書きされることはありませんが、それでもシステム リソースを消費し、ファイルが配置されているファイル システムをアンマウントできなくなる可能性があります。ファイル記述子 0、1、2 を持つ 3 つのファイル (ファイル記述子の概念については次の章で説明します) (通常、入力ファイル、出力ファイル、エラー ファイルと呼ばれるもの) も閉じる必要があることに注意してください。 。多くの読者はこれについて疑問に思うでしょう。入力と出力は必要ではないでしょうか。しかし、実際には、上記のステップ 2 の後、デーモン プロセスは、それが属する制御端末との接続を失うことになります。デーモンプロセスに到達する文字が多く、デーモンプロセスが従来の方法(printfなど)で出力した文字は、弊社の端末では表示できません。したがって、これら 3 つのファイルは存在価値を失っているため、閉じるべきです。

PHP を使用して Gearman のワーカー デーモンを作成する

前回の記事ではGearmanの使い方を紹介しました。私のプロジェクトでは、PHP を使用して、常に実行されるワーカーを作成します。 Gearman が推奨する例に従い、単純なループでタスクを待機する場合、次のようないくつかの問題が発生します。 1. コードが変更されたとき、コードの変更をどのように有効にするか。 2. ワーカーを再起動するとき。 、タスク処理が完了した後に現在の再起動を確認する方法。

この問題に対応して、次の解決策を検討しました:

1. コードを変更するたびに、ワーカーを手動で再起動する必要があります (最初に強制終了してから開始します)。これは、構成ファイルの再ロードの問題のみを解決します。

2. Worker に設定し、単一のタスク サイクルが完了したら Worker を再起動します。このソリューションの問題は、多額の費用がかかることです。

3. ワーカーに終了関数を追加します。ワーカーが終了する必要がある場合は、クライアントに高い優先順位で終了呼び出しを送信します。これにはクライアントの協力が必要ですが、バックグラウンド タスクを使用する場合には適していません。

4. ワーカーでファイルが変更されているかどうかを確認し、変更されている場合は、ワーカー自体を終了して再起動します。

5. ワーカーのシグナル制御を書き込み、http の正常な再起動命令と同様の再起動命令を受け入れます。

最後に、方法 4 と 5 を組み合わせることで、このようなデーモンを実装できます。設定ファイルが変更されると、ユーザーの kill -1 pid シグナルを受信すると、デーモンも自動的に再起動します。

コードは次のとおりです:

クリップボードにコピーLiehuo.Net Codes引用内容:[www.bkjia.com]
declare(ticks = 1 );
// このケースでは、設定ファイルを定期的にチェックし、設定ファイルが変更された場合は自動的に再起動します
// デーモンを正常に再起動したい場合は、デーモンに HUP シグナルを与えます
// by shiqiang 2011 年 12 月 4 日時点

$init_md5 = md5_file( 'config.php');

// シグナルハンドラーを登録します
pcntl_signal( SIGALRM, "signal_handler", true );
pcntl_signal( SIGHUP, 'signal_handler', TRUE );

$job_flag = FALSE; // ジョブが完了したかどうかを示すジョブ ステータス フラグ
$signal_flag = FALSE; // kill -1 シグナルを受信したかどうかを正当化するシグナル ステータス フラグ

while( 1 ){
$job_flag = FALSE; //ジョブステータスフラグ
print "Worker start running ... n";
睡眠(5);
print "作業者のタスクは完了しました ... n";
$フラグ = TRUE; //ジョブステータスフラグ
AutoStart( $signal_flag );
}

function signal_handler( $signal ) {
global $job_flag;
グローバル $signal_flag;

switch( $signal ){
case SIGQUIT:
print date('y-m-d H:i:s', time() ) 。 " シグナルをキャッチしました : SIGQUIT - いいえ : $signal n";
終了(0);
休憩;
case SIGSTOP:
print date('y-m-d H:i:s', time() ) 。 " シグナルをキャッチしました : SIGSTOP - いいえ : $signal n";
休憩;
ケースサインアップ:
print date('y-m-d H:i:s', time() ) 。 " シグナルをキャッチしました : SIGHUP - いいえ : $signal n";
if( $flag === TRUE ){
AutoStart( TRUE );
}else{
$signal_flag = TRUE;
}
休憩;
case SIGALRM:
print date('y-m-d H:i:s', time() ) 。 " 信号をキャッチしました : SIGALRM - いいえ : $signal n";
//pcntl_exec( '/bin/ls' );
pcntl_alarm( 5 );
休憩;
デフォルト:
ブレイク;
}
}

function AutoStart( $signal = FALSE, $filename = 'config.php' ){
global $init_md5;

if( $signal || md5_file( $filename ) != $init_md5 ){
print "設定ファイルが変更されたので、再起動します。n";
$pid = pcntl_fork();
if( $pid == -1 ){
print "フォークエラー n";
}else if( $pid > 0 ){
print "親出口 n";
終了(0);
}else{
$init_md5 = md5_file( $filename );
print "子供は n を走り続けます";
}
}
}

(本文来源:博客园、著者:小狼の世界)

www.bkjia.comtru​​ehttp://www.bkjia.com/PHPjc/363858.html技術記事これはデーモンです、これはまた興味深い概念です、デーモンは英語で精灵的意思決定です、就像我们经常迪斯尼アニメーション画里见に見られるもの、いくつかの会飞、いくつかの不会、经...
声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。