我目前正在上计算机系统课程,但遇到了家庭作业问题。我必须创建这个特定的进程树:
我还需要它保持这种状态一段时间(使用 sleep()),以便用户可以使用 pstree 在终端中查找它并查看它是否存在。然后它必须向后终止(首先是 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
理想情况下,“parent Knows child 2828 finish with a return value 1”这行应该一直放在最后。提前致谢!
答案1
你必须使用sleep
来阻止C立即退出。但在你的结构中,A 等待 C 退出,然后再生成 B 和 D。
所以 :
- 将 C 的块放在与B 的块
wait
相同的位置wait
- 在C退出之前添加睡眠(也在B和D退出之前)
- 因为你不想等待 B 两倍的时间,所以确保 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