
私は現在コンピュータシステムコースを受講していますが、宿題に問題があります。次の特定のプロセスツリーを作成する必要があります。
また、ユーザーがpstreeを使用して端末から検索してそこにいることを確認できるように、しばらくの間(sleep()を使用)この状態を維持する必要があります。その後、戻る必要があります(最初にD、B、Cの順に)。これまではツリーを作成できますが、ツリーの残りの部分が作成される前にアイテムCが終了するため、A-> B-> Dでのみ終了します。私のexit(1)行のためにこれが発生することはわかりますが、それをどこに置くべきか、他の方法があるかどうかはわかりません。
これまで私のコードは次のようになります。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
int status = 0;
printf("I am: %d\n\n", (int)getpid());
pid_t pid = fork(); // fork a child
if(pid == 0)
{
printf("Hi I'm process %d and my parent is %d\n",getpid(),getppid());
exit(1);
}
else
{
pid_t childPid = wait(&status);
int childReturnValue = WEXITSTATUS(status);
printf("parent knows child %d finished with return value %d\n\n", (int) childPid, childReturnValue);
pid_t pid = fork(); // fork a child
if (pid == 0)
{
printf("Hi I'm process %d and my parent is %d.\n", getpid(), getppid());
pid = fork(); // fork a child
if (pid == 0)
{
printf("Hi I'm process %d and my parent is %d.\n",getpid(),getppid());
exit(3);
}
else
{
pid_t childPid = wait(&status);
int childReturnValue = WEXITSTATUS(status);
printf("parent knows child %d finished with return value %d\n\n", (int) childPid, childReturnValue);
}
exit(2);
}
else
{
pid_t childPid = wait(&status);
int childReturnValue = WEXITSTATUS(status);
printf("parent knows child %d finished with return value %d\n\n", (int) childPid, childReturnValue);
}
}
return 0;
}
これは私が現在得た結果です。
I am: 2827
Hi I'm process 2828 and my parent is 2827
parent knows child 2828 finished with return value 1
Hi I'm process 2829 and my parent is 2827.
Hi I'm process 2830 and my parent is 2829.
parent knows child 2830 finished with return value 3
parent knows child 2829 finished with return value 2
理想的には、「親は子2828が戻り値1で終わることを知っています」行は常に最後になければなりません。よろしくお願いします!
答え1
sleep
Cがすぐにシャットダウンしないようにするために使用する必要があります。ただし、構造では、AはBとDを生成する前にCが終了するのを待ちます。
だから:
wait
CのブロックをBのブロックと同じ位置に置きます。wait
- Cが終了する前に(またBとDが終了する前に)スリープモードを追加する
- Bよりも2倍長く待たないので、Bの睡眠がDの待機よりも前にあることを確認してください。
- 各子プロセスの正しい戻り値を取得するには、代わりにを
waitpid
使用する必要がありますwait
。
完全なコードは次のとおりです。
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#define SLEEP_TIME 5
int main() {
int status;
printf("I am: %d\n\n", (int)getpid());
pid_t c_pid = fork(); // fork a child
if(c_pid == 0)
{
printf("Hi I'm process C (%d) and my parent is %d\n",getpid(),getppid());
sleep(SLEEP_TIME);
exit(1);
}
else
{
pid_t b_pid = fork(); // fork a child
if (b_pid == 0)
{
printf("Hi I'm process B (%d) and my parent is %d.\n", getpid(), getppid());
pid_t d_pid = fork(); // fork a child
if (d_pid == 0)
{
printf("Hi I'm process D (%d) and my parent is %d.\n",getpid(),getppid());
sleep(SLEEP_TIME);
exit(3);
}
else
{
// sleep before wait - actually no effect as the wait for D also waits for SLEEP_TIME
sleep(SLEEP_TIME);
// Wait for D to quit
waitpid(d_pid, &status, 0);
int DReturnValue = WEXITSTATUS(status);
printf("parent knows child D (%d) finished with return value %d\n\n", (int) d_pid, DReturnValue);
}
exit(2);
}
else
{
sleep(SLEEP_TIME);
// Wait for B to quit
waitpid(b_pid, &status, 0);
int BReturnValue = WEXITSTATUS(status);
printf("parent knows child B (%d) finished with return value %d\n\n", (int) b_pid, BReturnValue);
// Wait for C to quit
waitpid(c_pid, &status, 0);
int CReturnValue = WEXITSTATUS(status);
printf("parent knows child C (%d) finished with return value %d\n\n", (int) c_pid, CReturnValue);
}
}
return 0;
}
対応する出力は次のとおりです。
私:24450
こんにちは。私はプロセスC(24451)で、親プロセスは24450です。
こんにちは。私はプロセスB(24452)で、親プロセスは24450です。
こんにちは。私はプロセスD(24453)で、親プロセスは24452です。
親は子D(24453)が完了し、値3を返したことを知っています。
親は、子B(24452)が完了し、値2を返したことを知っています。
親は子C(24451)が完了し、値1を返したことを知っています。