基于以下代码,我一直在尝试制作进程树。起初,我以为它类似于对称的二叉树,但不再这样。
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main() {
int status;
pid_t i;
i = fork();
wait(&status);
printf("a; i = %d\n", i);
i = fork();
wait(&status);
printf("b; i = %d\n", i);
i = fork();
wait(&status);
printf("c; i = %d\n", i);
i = fork();
wait(&status);
printf("d; i = %d\n", i);
return 0;
}
此外,运行此代码时,输出的数量是我最初预测的数量的2倍。例如,d
被打印了16次,但我认为它只会被打印8次。任何更深入的解释都将有所帮助。
答案 0 :(得分:3)
为帮助您自己理解,请在每个printf()
语句中包含PID和PPID。同样,捕获并报告wait()
每次调用时返回的值(死子PID);您可以决定是否报告status
,但是如果wait()
调用由于没有子项而失败,则将其初始化为零。通常,孩子会在父母从wait()
调用返回之前继续。
或者更好的是编写一个日志记录功能,可以为您处理详细信息。 例如,考虑以下代码:
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
static void print_info(const char *tag, int corpse, int status, int child)
{
int pid = getpid();
int ppid = getppid();
printf("PID %5d, PPID %5d: %s (corpse: %5d, status 0x%.4X), child %5d\n",
pid, ppid, tag, corpse, status, child);
}
int main(void)
{
int pid = getpid();
int ppid = getppid();
printf("Initial PID %5d, PPID %5d:\n", pid, ppid);
int status = 0;
int child = fork();
int corpse = wait(&status);
print_info("a", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("b", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("c", corpse, status, child);
child = fork();
corpse = wait(&status);
print_info("d", corpse, status, child);
return 0;
}
示例运行为我提供了
Initial PID 7357, PPID 20754:
PID 7358, PPID 7357: a (corpse: -1, status 0x0000), child 0
PID 7359, PPID 7358: b (corpse: -1, status 0x0000), child 0
PID 7360, PPID 7359: c (corpse: -1, status 0x0000), child 0
PID 7361, PPID 7360: d (corpse: -1, status 0x0000), child 0
PID 7360, PPID 7359: d (corpse: 7361, status 0x0000), child 7361
PID 7359, PPID 7358: c (corpse: 7360, status 0x0000), child 7360
PID 7362, PPID 7359: d (corpse: -1, status 0x0000), child 0
PID 7359, PPID 7358: d (corpse: 7362, status 0x0000), child 7362
PID 7358, PPID 7357: b (corpse: 7359, status 0x0000), child 7359
PID 7363, PPID 7358: c (corpse: -1, status 0x0000), child 0
PID 7364, PPID 7363: d (corpse: -1, status 0x0000), child 0
PID 7363, PPID 7358: d (corpse: 7364, status 0x0000), child 7364
PID 7358, PPID 7357: c (corpse: 7363, status 0x0000), child 7363
PID 7365, PPID 7358: d (corpse: -1, status 0x0000), child 0
PID 7358, PPID 7357: d (corpse: 7365, status 0x0000), child 7365
PID 7357, PPID 20754: a (corpse: 7358, status 0x0000), child 7358
PID 7366, PPID 7357: b (corpse: -1, status 0x0000), child 0
PID 7367, PPID 7366: c (corpse: -1, status 0x0000), child 0
PID 7368, PPID 7367: d (corpse: -1, status 0x0000), child 0
PID 7367, PPID 7366: d (corpse: 7368, status 0x0000), child 7368
PID 7366, PPID 7357: c (corpse: 7367, status 0x0000), child 7367
PID 7369, PPID 7366: d (corpse: -1, status 0x0000), child 0
PID 7366, PPID 7357: d (corpse: 7369, status 0x0000), child 7369
PID 7357, PPID 20754: b (corpse: 7366, status 0x0000), child 7366
PID 7370, PPID 7357: c (corpse: -1, status 0x0000), child 0
PID 7371, PPID 7370: d (corpse: -1, status 0x0000), child 0
PID 7370, PPID 7357: d (corpse: 7371, status 0x0000), child 7371
PID 7357, PPID 20754: c (corpse: 7370, status 0x0000), child 7370
PID 7372, PPID 7357: d (corpse: -1, status 0x0000), child 0
PID 7357, PPID 20754: d (corpse: 7372, status 0x0000), child 7372
您可以逐一浏览数据,看看有4个fork()
调用有2 4 个进程(每个调用之后,有2个进程之前有1个进程,因此在一个调用之后,有2个进程;在2个调用之后,有4个进程,依此类推),并且子进程在父进程继续之前退出(因此,在此示例中,PID 7357是最后打印{{1 }}标签,a
标签,b
标签和c
标签)。
每当您在跟踪过程树时遇到困难时,请使用与此类似的打印技术来帮助您了解正在发生的事情。