親プロセスが死んだときの新しい親プロセス


22

UNIXでは、親プロセスが消えると、すべての子プロセスが親としてinitをリセットすると考えました。これは常に正しくないですか?例外はありますか?

回答:


5

コメントを回答に移します。例外はないと思います。

これは、「子プロセスが殺される前に親プロセスが殺されることもあります。この場合、「すべてのプロセスの親」initプロセスは新しいPPID(親プロセスID)になります。ソース

同様に、IBMのブログで説明されています。「親は子の前に死ぬか、殺されます。上記のシナリオでは、子プロセスは親を失ったために孤立プロセスになります。Linuxでは、initプロセスは孤立したプロセスとそれらを採用します。つまり、子が親を失った後、そのinitプロセスは新しい親プロセスになります。


61

2014年に書かれた3つの回答では、すべてがUnicesおよびLinuxで、プロセスは例外なくプロセス#1に親に変更されたと述べています。3つの間違った答え。☺

SUSは言い、ここで他の回答の一つに引用されたので、私は再びそれを引用しませんが、孤児の親プロセスがに設定されている実装定義のプロセス。Cristian Ciupituは、Linuxのドキュメントを参照して、実装の定義を確認する権利があります。しかし、彼は一貫性がなく、最新ではないそのドキュメントに惑わされています。

これらの3つの答えが書かれる2年前、そしてこの答えを最初に書いた3年前に急いでLinuxカーネルが変わりました。systemd開発者は、プロセスが自身を「サブリーパー」として設定する機能を追加しました。Linux 3.4以降では、プロセスprctl()PR_SET_CHILD_SUBREAPERオプションを使用してシステムコールを発行できます。その結果、プロセス#1ではなく、プロセスが親のない子孫プロセスの親になります。のマニュアルページprctl()は最新ですが、他のマニュアルページは最新のものではなく、一貫性が保たれています。

バージョン10.2では、FreeBSDは同じ機能を獲得し、既存のprocctl()システムコールPROC_REAP_ACQUIREPROC_REAP_RELEASEオプションを拡張しました。DragonFly BSDからこのメカニズムを採用しました。これはバージョン4.2で獲得しましreapctl()procctl()。当初は名前が付けられていましたが、開発中に名前が変更されました。

したがって、例外があり、かなり顕著な例外があります。Linux、FreeBSD / PC-BSD、およびDragonFly BSDでは、孤立した子の親プロセスは、サブリーパーまたはプロセス#1としてマークされた子の最も近い先祖プロセスに設定されます。祖先サブリーパープロセスがない場合。systemd(開発者が最初にこれをLinuxカーネルに組み込んだもの)、upstart、およびnoshを含むさまざまなデーモン監視ユーティリティは、service-managerすでにこれを利用しています。

そのようなデーモンスーパーバイザーがプロセス#1でなく、対話型ログインセッションなどのサービスを生成し、そのセッションで、ダブルで「デーモン化」しようとする(まったく間違った)トリックをfork()実行すると、プロセスはプロセス#1の子ではなく、デーモンスーパーバイザーの子になります。もちろん、ログインセッション内から直接デーモンを生成できることを期待することは、根本的な間違いです。しかし、それは別の答えです。

参考文献


私は実際に、孤立したプロセスがセッションの初期化に関連付けられていることに気付いていました(UbuntuでUpstartを使用)が、その重要性を認識していませんでした。+1
ムル

特にupstartセッションの初期化の詳細については、unix.stackexchange.com / a / 194208/5132を参照してください。
JdeBP

8

exitThe SingleUNIX®Specification、バージョン2 のmanページによると:

すべての呼び出しプロセスの既存の子プロセスとゾンビプロセスの親プロセスIDは、実装依存のシステムプロセスのプロセスIDに設定されます。つまり、これらのプロセスは特別なシステムプロセスに継承されます。

ほとんどのUnixバリアントでは、その特別なプロセスはinit(PID 1)です。

Linuxのwait(2)manページでこれを確認しています。

親プロセスが終了すると、その「ゾンビ」の子(もしあれば)がinit(8)によって採用され、自動的にゾンビを削除するための待機が実行されます。

FreeBSD wait(2)、NetBSD wait(2)、OpenBSD wait(2)、およびMac OS Xのwait(2)マニュアルページでもこれが確認されています。

すべての子プロセスが終了するのを待たずに親プロセスが終了した場合、残りの子プロセスには親プロセス1 ID(initプロセスID)が割り当てられます。

Oracle Solaris 11.1のwait(3C)マニュアルページでもこれが確認されています。

子プロセスの終了を待たずに親プロセスが終了した場合、各子プロセスの親プロセスIDは1に設定され、初期化プロセスは子プロセスを継承します。をご覧くださいIntro(2)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.