VirtualBoxを使用してWindows 8.1でUbuntu 14.04 LTSを実行しています。オペレーティングシステムにアクセスしていますが、次のプログラムで奇妙な結果が表示されます。
#include <stdio.h>
#include <unistd.h>
int main() {
printf("I'm the parent, my PID is %d, my parent is process %d\n",
getpid(), getppid());
fork();
printf("This sentence has been printed by process: %d my parent is process %d\n",
getpid(), getppid());
return 0;
}
GCCでコンパイルして実行しました。その後、出力は次のようになります。
kocks@kocks-VirtualBox:~$ ./uno
I'm the parent, my PID is 3746, my parent is process 3507
This sentence has been printed by process: 3746 my parent is process 3507
kocks@kocks-VirtualBox:~$ This sentence has been printed by process: 3747 my parent is process 2857
問題は3番目の文にあります。私は「親プロセスは3746です」と予想しました。特に、数字(2857)は常に同じで、VMを再起動した後にのみ変更されます。追加するいくつかの点があります。
wait()
返す前に追加すると完璧に動作します。- 仮想マシンを「プリンセス」しようとすると(2つのプロセッサ、メモリの追加など)、ランダムに正しい出力が返されることがあります。
では、問題は仮想マシンにあるようですが、そうですか?この問題をどのように解決できますか?
編集する デュアルブートでUbuntuでプログラムを実行すると、出力は次のようになります。
I'm the parent, my PID is 3186, my parent is process 2454
This sentence has been printed by process: 3186 my parent is process 2454
This sentence has been printed by process: 3187 my parent is process 3186
どうやってこれができますか?
答え1
私はOS Xをホストとして使用し、クライアントごとに1つのCPUのみを割り当てる2つの仮想マシン設定でテストしました。
1 Ubuntu 14.04.2
この設定では、X Window環境での動作はOPの動作と一致します。
john@U64D:~$ ./a
I'm the parent, my PID is 2682, my parent is process 2632
This sentence has been printed by process: 2682 my parent is process 2632
john@U64D:~$ This sentence has been printed by process: 2683 my parent is process 1673
親プロセス1673は、ログアウトして再度ログインするまで同じままです。
john@U64D:~$ ./a
I'm the parent, my PID is 3787, my parent is process 3740
This sentence has been printed by process: 3787 my parent is process 3740
john@U64D:~$ This sentence has been printed by process: 3788 my parent is process 3107
./a
I'm the parent, my PID is 3790, my parent is process 3740
This sentence has been printed by process: 3790 my parent is process 3740
john@U64D:~$ This sentence has been printed by process: 3791 my parent is process 3107
3107初期化 - ユーザー
john@U64D:~$ ps -ef|grep 3107
john 3107 2911 0 15:07 ? 00:00:00 init --user
ただし、X以外の環境(例:tty1)では、結果はBarmarの答えと一致します。
2 Debian 7.8
この設定は、X 環境と X 以外の環境の両方に対する Barmar の回答と一致します。
ジョン@ Debian:~$ ./a
I'm the parent, my PID is 3455, my parent is process 3406
This sentence has been printed by process: 3455 my parent is process 3406
john@debian:~$ This sentence has been printed by process: 3456 my parent is process 1
結論として
OP観測は、基本X環境でセッション初期化を使用するUbuntuの結果です。セッション初期化の詳細を確認できます。ここ。
答え2
使用しないと、wait()
子供が走る前に親が終了する可能性があります。子プロセスが呼び出されると、getppid()
親プロセスはすでに終了しているため、子プロセスが採用されますinit
。一般的なUnix実装では、PIDはinit
1なので、次のように期待できます。私の両親はプロセス1です。このようなことが起こった場合。しかし、明らかにVirtualBoxはこれを変更しました。
を使用すると、wait()
終了する前に親が子が完了するのを待ちます。こうすれば、その子は決して孤児にならないでしょう。