gpt4 book ai didi

c - 这段代码中fork和pid(if(pid!= 0))如何工作?

转载 作者:行者123 更新时间:2023-11-30 14:43:26 25 4
gpt4 key购买 nike

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main()
{
int pid;
int x, y;

x = 10;
y = 10;
pid = fork();

if (pid != 0)
{
x++;
y--;
}

printf("x = %i y = %i\n", x, y);

pid = fork();

if (pid != 0)
{
x++;
y--;
}
printf("x = %i y = %i\n", x, y);

return (0);
}


我对这部分代码完全感到困惑。谁能解释我的工作原理?
我也不明白哪个过程(孩子/父母)可以打印。

最佳答案

fork()功能不常见;除非失败,否则它将返回两次,在两个不同(但密切相关)的过程中的每个过程中返回一次。如果失败,则返回-1(在原始过程中,必不可少)。如果成功,它将在子进程中返回0,而在原始(父)进程中返回子进程的PID,该PID绝不会为0(或负数)。

您应该学习如何编写代码。在使用fork()的代码的上下文中,通常有效的方法是打印PID(进程ID)和PPID(父进程ID),以帮助消除哪个进程打印什么内容的歧义。对于有关哪个进程将打印的问题的简短答案是,两个进程将打印第一个printf()调用中的数据,而四个进程将打印第二个printf()调用中的数据–除非您将程序的输出通过管道传输到另一个( (例如cat),在这种情况下,似乎某些进程会多次打印数据。 (另请参见printf() anomaly after fork()。)

让我们测试一下您的代码:

#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>

int main(void)
{
printf("PID = %d\n", (int)getpid());

int x = 10;
int y = 10;

int pid = fork();
if (pid != 0)
{
x++;
y--;
}
printf("1: x = %i y = %i (PID %d, PPID %d)\n",
x, y, (int)getpid(), (int)getppid());

pid = fork();
if (pid != 0)
{
x++;
y--;
}
printf("2: x = %i y = %i (PID %d, PPID %d)\n",
x, y, (int)getpid(), (int)getppid());

int status;
int corpse;
while ((corpse = wait(&status)) > 0)
{
printf("%d: child %d exited with status 0x%.4X\n",
(int)getpid(), corpse, status);
}

return (getpid() % 16);
}


main()末尾的return语句返回16中的15次非零退出状态,只是使事情变得更加有趣。

示例运行(从 ./fork43构建的程序 fork43.c)-一个不带管道,一个带管道:

$ ./fork43
PID = 26226
1: x = 11 y = 9 (PID 26226, PPID 23612)
2: x = 12 y = 8 (PID 26226, PPID 23612)
1: x = 10 y = 10 (PID 26227, PPID 26226)
2: x = 11 y = 9 (PID 26228, PPID 26226)
2: x = 11 y = 9 (PID 26227, PPID 26226)
26226: child 26228 exited with status 0x0400
2: x = 10 y = 10 (PID 26229, PPID 26227)
26227: child 26229 exited with status 0x0500
26226: child 26227 exited with status 0x0300
$ ./fork43 | cat
PID = 26230
1: x = 11 y = 9 (PID 26230, PPID 23612)
2: x = 11 y = 9 (PID 26233, PPID 26230)
PID = 26230
1: x = 10 y = 10 (PID 26232, PPID 26230)
2: x = 10 y = 10 (PID 26234, PPID 26232)
PID = 26230
1: x = 10 y = 10 (PID 26232, PPID 26230)
2: x = 11 y = 9 (PID 26232, PPID 26230)
26232: child 26234 exited with status 0x0A00
PID = 26230
1: x = 11 y = 9 (PID 26230, PPID 23612)
2: x = 12 y = 8 (PID 26230, PPID 23612)
26230: child 26233 exited with status 0x0900
26230: child 26232 exited with status 0x0800
$


在第一次运行中,初始(父)进程具有PID26226。它进行分叉,其子进程为26227。父进程被告知其子PID,因此它递增 x并递减 y;然后,它执行 printf()语句,其中格式字符串以 1:开头,将值 x打印为11,将 y打印为9。在此运行中,父进程再次派生使用PID 26228创建其第二个子级。父级再次递增 x并递减 y,并执行 printf()语句,在此语句之前,格式字符串以 2:开头。然后,它到达 wait()循环并等待其子级之一死亡。

然后,第一个子进程(26227)执行 printf()语句,其中格式字符串以 1:开头,但 xy的值均保持为10。然后到达第二个fork,并创建自己的子进程(原始流程的孙代)具有PID 26229的流程。

第二个子项26228具有(x,y)个值(11,9),因为这些是分叉时的值,因此当它执行 printf()语句(格式字符串以 2:开头)时,它将打印这些值。

在第一个子派生之后,它会被告知其孩子的PID,因此它递增 x并递减 y,并打印值11和9。

第二个孩子退出,其状态由原始过程报告。孙子进程现在执行 printf()语句,其中以 2:1. Since the value in pid was 0 twice, the values in x and y`开头的格式字符串仍保持为10。然后退出。

第一个孩子可以报告其孩子已经退出,然后自己退出。父进程报告第一个孩子退出并且也退出。

总体而言,有一个 PID输出副本,两个 1:复制副本和4个 2:复制副本(以及三个“退出子项”报告)。

第二次运行将输出传递到 cat,表明输出已完全缓冲,而不是行缓冲,因此进程在退出时刷新写入的数据,而不是在打印换行符时刷新。这就是为什么有4个副本 PID = 26230输出和4个 1:输出的原因。仍然只有3个“儿童退出”报告。

这样打印PID信息对于理解代码很有帮助。重要的是要认识到输出顺序不是固定的。仅由于调度算法以及计算机上同时发生的其他事情,不同的运行可能会产生不同的序列(与不同的PID编号完全不同)。

关于c - 这段代码中fork和pid(if(pid!= 0))如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53925416/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com