Linuxデーモンプロセスの原理と実現
5039 ワード
一、デーモンプロセスの概要
linuxまたはunixオペレーティングシステムでは、システムの起動時に多くのサービスが開始されます.これらのサービスはデーモンプロセスと呼ばれます.柔軟性を向上させるために、rootはシステムがオンになっているモードを選択することができます.これらのモードは実行レベルと呼ばれ、各実行レベルは一定の方法でシステムを構成します.デーモンプロセスは、端末から離れてバックグラウンドで実行されるプロセスです.デーモンプロセスが端末から離れるのは、プロセスが実行中の情報が任意の端末に表示され、プロセスが任意の端末によって生成された端末情報によって中断されないようにするためである.
二、デーモンプロセスの概要
デーモンプロセス、いわゆるDaemonプロセスは、Linuxのバックグラウンドサービスプロセスです.これは、通常、制御端末とは独立して、あるタスクを周期的に実行したり、発生したイベントの処理を待ったりする生存期間の長いプロセスです.デーモン・プロセスは、システム・ブート・マウント時に開始され、システムが閉じたときに終了することが多い.Linuxシステムには多くのデーモンプロセスがあり、多くのサービスはデーモンプロセスによって実現されます.また、デーモンプロセスは、ジョブ計画プロセスcrond、印刷プロセスlqdなど、多くのシステムタスクを完了することができます(ここでの末尾文字dはDaemonの意味です).
Linuxでは、各システムがユーザと交流するインタフェースを端末と呼ぶため、この端末から実行される各プロセスはこの端末に依存し、この端末はこれらのプロセスの制御端末と呼ばれ、制御端末が閉じられると、対応するプロセスは自動的に閉じられる.しかし、デーモンプロセスは、システム全体が閉じるまで実行されてから終了するという制限を突破することができます.あるプロセスがユーザや端末や他の変化によって影響を受けないようにするには、このプロセスをデーモンプロセスにする必要があります.
三、デーモンの作成
子プロセスの作成、親プロセスの終了
これは、デーモンプロセスを記述する最初のステップです.デーモンプロセスは制御端末から離れているため,最初のステップが完了するとシェル端末にプログラムが実行されたという仮象をもたらす.その後のすべての作業はサブプロセスで完了し,ユーザはShell端末で他の命令を実行することができ,制御端末からの離脱を形式的に行うことができる.Linuxでは、親プロセスがサブプロセスより先に終了すると、サブプロセスが孤児プロセスになり、システムが孤児プロセスを発見するたびに、自動的に1番プロセス(init)によって養子縁組され、元のサブプロセスがinitプロセスのサブプロセスになります.サブプロセスでの新しいセッションの作成
このステップは、実装は非常に簡単ですが、その意味は非常に重要です.ここではシステム関数setsidを使用します.setsidを具体的に説明する前に、プロセスグループとセッション期間の2つの概念を理解します.≪プロセス・グループ|Process Group|ldap≫:1つ以上のプロセスの集合です.プロセスグループには、プロセスグループIDがあり、一意に識別されます.プロセス番号(PID)に加えて、プロセスグループIDもプロセスの必須属性です.各プロセスグループには、プロセスグループIDに等しいプロセス番号を持つグループ長プロセスがあります.プロセスグループIDは、チーム長プロセスの終了によって影響を受けない.≪セッション期間|Session Period|emdw≫:セッション期間は、1つ以上のプロセス・グループの集合です.通常、1つのセッションはユーザーログインで開始され、ユーザー終了で終了します.この間、ユーザーが実行したすべてのプロセスはこのセッション期間に属します.次に、setsidに関する内容を具体的に説明します.setsid関数の役割:setsid関数は、新しいセッションを作成し、そのセッショングループのグループ長を担当するために使用されます.setsidを呼び出すには、次の3つの役割があります.では、デーモンプロセスを作成するときにsetsid関数を呼び出すのはなぜですか?デーモンの作成の最初のステップがfork関数を呼び出してサブプロセスを作成したため、親プロセスを終了します.fork関数を呼び出すと、サブプロセスは親プロセスのセッション期間、プロセスグループ、制御端末などを全面的にコピーするため、親プロセスは終了したが、セッション期間、プロセスグループ、制御端末などは変化しないため、これは本当の意味での独立ではなく、setsid関数はプロセスを完全に独立させ、他のプロセスの制御から抜け出すことができる.
現在のディレクトリをルートに変更
というステップも必要です.forkを使用して作成されたサブプロセスは、親プロセスの現在の作業ディレクトリを継承します.プロセスの実行中に、現在のディレクトリが存在するファイルシステム(例えば「/mnt/usb」)はアンインストールできないため、システムが何らかの理由でシングルユーザモードに入るなど、今後の使用に多くのトラブルをもたらします.したがって、通常は、プロセスを保護する現在の作業ディレクトリとして「/」を使用することで、上記の問題を回避できます.もちろん、特別な必要があれば、/tmpなどの現在の作業ディレクトリを別のパスに変更することもできます.作業ディレクトリの一般的な関数式chdirを変更します.ファイル権限マスクのリセット
ファイル権限マスクとは、ファイル権限の対応するビットをマスクすることを意味する.たとえば、ファイル権限マスクが050であると、ファイルグループ所有者の読み取り可能および実行可能な権限がブロックされます.fork関数を使用して新しいサブプロセスが親プロセスのファイル権限マスクを継承するため、このサブプロセスがファイルを使用するのに多くのトラブルが発生します.したがって、ファイル権限マスクを0に設定すると、デーモンプロセスの柔軟性が大幅に向上します.ファイル権限マスクを設定する関数はumaskです.ここで、通常の使用方法はumask(0)である.ファイル記述子を閉じる
ファイル権限コードと同様に、fork関数で新規作成されたサブプロセスは、親プロセスから開いているファイルを継承します.これらの開いているファイルは、デーモンプロセスによって読み書きされない場合がありますが、システムリソースが消費され、ファイルシステムが取り外すことができない可能性があります.上記の第2のステップの後、デーモンプロセスは所属する制御端末と連絡を失った.したがって、端末から入力された文字がデーモンプロセスに達することは不可能であり、デーモンプロセスでprintfなどの従来の方法で出力された文字が端末に表示されることも不可能である.したがって、ファイル記述子が0、1、2の3つのファイル(入力、出力、エラー)は、存在価値を失い、閉じるべきである.通常、ファイル記述子を閉じるには、===============================
for(i=0;i<MAXFILE;i++)
close(i);
===============================
デーモンプロセス終了処理
ユーザーが外部でデーモンプロセスの実行を停止する必要がある場合、killコマンドを使用してデーモンプロセスを停止することが多い.従って、ガードプロセスではkillからのsignal信号処理を実現するために符号化が必要であり、プロセスの正常な終了を達成する.四、デーモンプロセスの完全なインスタンス(10 sおきに/tmp/dameon.logに一言を書き込む)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<fcntl.h>
#include<sys/types.h>
#include<unistd.h>
#include<sys/wait.h>
#include <signal.h>
#define MAXFILE 65535
volatile sig_atomic_t _running = 1;
void sigterm_handler(int arg)
{
_running = 0;
}
int main()
{
pid_t pc, pid;
int i, fd, len;
char *buf = "this is a Dameon
";
len = strlen(buf);
//
pc = fork();
if(pc < 0)
{
printf("error fork
");
exit(1);
}
else if(pc > 0)
{
exit(0);
}
//
setsid();
pid = fork();// [1]
if (pid < 0)
{
perror("fork error");
}
if (pid > 0)
{
exit(0);
}
//
chdir("/");
//
umask(0);
//
for(i = 0;i < MAXFILE; i++)
{
close(i);
}
signal(SIGTERM, sigterm_handler);
while( _running )
{
if((fd = open("/tmp/dameon.log", O_CREAT | O_WRONLY | O_APPEND, 0600)) < 0)
{
perror("open");
exit(1);
}
write(fd, buf, len);
close(fd);
usleep(10 * 1000);//10
}
}