ソースコードで次の関数を見つけました。猫の目(ミニマリストウィンドウマネージャ):
void spawn(const Arg arg) {
if(fork() == 0) {
if(fork() == 0) {
if(dis)
close(ConnectionNumber(dis));
setsid();
execvp((char*)arg.com[0],(char**)arg.com);
}
exit(0);
}
}
なぜ単にそうでないのか理解できません。
void spawn(const Arg arg) {
if(fork() == 0) {
if(dis)
close(ConnectionNumber(dis));
setsid();
execvp((char*)arg.com[0],(char**)arg.com);
}
}
?ここでdoubleを使用すると、どのような利点がありますかfork()
?
答え1
次の節は、StevensとRagoの記事を引用したものです。UNIX環境の高度なプログラミング、デーモンを作成するための6つのコーディング規則のうち2つを説明します。特に、参照したい場合に備えて、図13.1にリストされている単一の関数daemonize
でこれを実装しました。
- フォークを呼び出し、親が終了するようにします。ここにはいくつかあります。まず、デーモンが単純なシェルコマンドで始まる場合、親プロセスを終了させると、シェルはコマンドが完了したと考えます。第二に、子プロセスは親プロセスのプロセスグループIDを継承しますが、新しいプロセスIDを取得するので、子プロセスがプロセスグループリーダーではないことを確認できます。これは後のsetid呼び出しの前提条件です。
- 新しいセッションを作成するには、setidを呼び出します。セクション9.5にリストされている3つのステップが発生します。プロセスは(a)新しいセッションのリーダーになり、(b)新しいプロセスグループのリーダーになり、(c)制御端末から切断されます。
- System V ベースのシステムでは、一部のユーザーはこの時点で fork を呼び出して親プロセスを終了し、子プロセスでデーモンを実行し続けることをお勧めします。これにより、デーモンはセッションリーダーではなく、System Vの規則(9.6節)に従って制御端末を取得できなくなります。または、制御端末のインポートを防ぐには、端末装置を開くときにO_NOCTTYを指定する必要があります。
変更したコードでは、親コードはexit()
呼び出し後に実行され続けます。spawn()
正確な動作は、spawn()
呼び出し後の内容によって異なります。