プロセスをデーモン化するためにfork()
の前にsetsid()
を使用する理由
基本的に、プロセスをその制御端末から切り離してプロセスグループリーダーにしたい場合は、setsid()
を使用します。
前にフォークせずにこれを行うことはできません。
どうして?
まず、setsid()は、プロセスをプロセスグループのリーダーにしますが、新しいセッションのリーダーにもなります。独自のプロセスグループを取得したいだけの場合は、setpgid(0,0)を使用します。
ここで、すでにプロセスグループリーダーまたはセッションリーダーである場合に、setsid()がEPERMを返す実際の理由を理解するには、プロセスグループとセッションIDが、それらを作成するプロセスのプロセスIDから初期化されることを理解する必要がありますセッションリーダーpid == sidおよびプロセスグループリーダーpid == pgidの場合)。また、プロセスグループはセッション間を移動できません。
つまり、あなたがプロセスグループリーダーであり、新しいセッションの作成が許可されている場合、sidとpgidはpidに設定され、古いプロセスグループ内の他のプロセスは奇妙な状態のままになります:プロセスグループリーダーが突然彼らは別のセッションにいるので、彼ら自身もそうかもしれません。そしてそれは許されないので、カーネルによるEPERMです。
ここでfork()を実行すると、セッションまたはプロセスグループのリーダーではなくなり、sidとpgidをpidに設定しても安全です。そのようなグループには他のプロセスがないためです。
だから、うん、考えてみれば、それはすべて理にかなっている。
fork()
を呼び出して子にsetsid()
を呼び出し、setsid()
を呼び出すプロセスがまだプロセスグループリーダーではないことを確認する必要があります(setsid()
は呼び出しプロセスをnewプロセスグループのプロセスグループリーダーにします。その場合は失敗します)。
_man 2 setsid
_、次の説明が表示されます:
呼び出しプロセスがプロセスグループリーダーでない場合、setsid()は新しいセッションを作成します。呼び出しプロセスは、新しいセッションのリーダーであり、新しいプロセスグループのプロセスグループリーダーであり、制御ターミナルはありません。呼び出しプロセスのプロセスグループIDとセッションIDは、呼び出しプロセスのPIDに設定されます。呼び出しプロセスは、この新しいプロセスグループとこの新しいセッションで唯一のプロセスになります。
プロセスグループリーダーがsetsid()
の呼び出しを許可されている場合、新しいセッションと新しいプロセスグループ(同じプロセスグループIDを持つ)を作成すると、プロセスグループIDの競合が発生します。