我真的很想分叉,这个代码中的pid是做什么的?有人可以解释一下X行和Y行的内容吗?
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#define SIZE 5
int nums[SIZE] = {0,1,2,3,4};
int main()
{
int i;
pid_t pid;
pid = fork();
if (pid == 0) {
for (i = 0; i < SIZE; i++) {
nums[i] *= -i;
printf("CHILD: %d ",nums[i]); /* LINE X */
}
}
else if (pid > 0) {
wait(NULL);
for (i = 0; i < SIZE; i++)
printf("PARENT: %d ",nums[i]); /* LINE Y */
}
return 0;
}
答案 0 :(得分:22)
fork()
重复该过程,因此在调用fork之后,实际上有2个程序实例正在运行。
您如何知道哪个进程是原始进程(父进程),哪个进程是新进程(父进程)?
在父进程中,从fork()
返回子进程的PID(将为正整数)。这就是if (pid > 0) { /* PARENT */ }
代码有效的原因。在子流程中,fork()
只返回0
。
因此,由于if (pid > 0)
检查,父进程和子进程将产生不同的输出,您可以看到here(由注释中的@jxh提供)。
答案 1 :(得分:15)
fork()的最简单示例
printf("I'm printed once!\n");
fork();
// Now there are two processes running one is parent and another child.
// and each process will print out the next line.
printf("You see this line twice!\n");
fork()的返回值。返回值-1 =失败; 0 =在子进程中; positive =在父进程中(返回值是子进程id)
pid_t id = fork();
if (id == -1) exit(1); // fork failed
if (id > 0)
{
// I'm the original parent and
// I just created a child process with id 'id'
// Use waitpid to wait for the child to finish
} else { // returned zero
// I must be the newly made child process
}
子进程与父进程有什么不同?
现在让我们可视化您的程序代码
pid_t pid;
pid = fork();
现在OS制作了两个相同的地址空间副本,一个用于父级,另一个用于子级。
父系统和子进程都在系统调用fork()之后立即开始执行。由于两个进程具有相同但独立的地址空间,因此在fork()调用之前初始化的那些变量在两个地址空间中具有相同的值。每个进程都有自己的地址空间,因此任何修改都将独立于其他进程。如果父级更改其变量的值,则修改将仅影响父进程的地址空间中的变量。 fork()sysem调用创建的其他地址空间即使具有相同的变量名也不会受到影响。
这里父pid非零,它调用函数ParentProcess()。另一方面,子进程为零,它调用ChildProcess(),如下所示:
在您的代码父进程调用wait()
中,它会暂停,直到子进程退出。所以孩子的输出首先出现。
if (pid == 0) {
// The child runs this part because fork returns 0 to the child
for (i = 0; i < SIZE; i++) {
nums[i] *= -i;
printf("CHILD: %d ",nums[i]); /* LINE X */
}
}
来自子流程的输出
第X行的内容
CHILD: 0 CHILD: -1 CHILD: -4 CHILD: -9 CHILD: -16
然后在子进程退出之后,父进程在wait()调用之后继续,然后打印其输出。
else if (pid > 0) {
wait(NULL);
for (i = 0; i < SIZE; i++)
printf("PARENT: %d ",nums[i]); /* LINE Y */
}
来自父流程的输出:
Y行的内容
PARENT: 0 PARENT: 1 PARENT: 2 PARENT: 3 PARENT: 4
最后,由子进程和父进程组合的两个输出将在终端上显示如下:
CHILD: 0 CHILD: -1 CHILD: -4 CHILD: -9 CHILD: -16 PARENT: 0 PARENT: 1 PARENT: 2 PARENT: 3 PARENT: 4
了解更多信息refer this link
答案 2 :(得分:4)
fork()
函数是特殊的,因为它实际上返回两次:一次返回父进程,一次返回子进程。在父进程中,fork()
返回子进程的pid。在子进程中,它返回0.如果发生错误,则不会创建子进程,并且会将-1返回给父进程。
成功调用fork()
后,子进程基本上与父进程完全相同。两者都有自己的所有本地和全局变量的副本,以及它们自己的任何打开文件描述符的副本。这两个进程同时运行,并且由于它们共享相同的文件描述符,因此每个进程的输出可能会相互交错。
仔细研究问题中的例子:
pid_t pid;
pid = fork();
// When we reach this line, two processes now exist,
// with each one continuing to run from this point
if (pid == 0) {
// The child runs this part because fork returns 0 to the child
for (i = 0; i < SIZE; i++) {
nums[i] *= -i;
printf("CHILD: %d ",nums[i]); /* LINE X */
}
}
else if (pid > 0) {
// The parent runs this part because fork returns the child's pid to the parent
wait(NULL); // this causes the parent to wait until the child exits
for (i = 0; i < SIZE; i++)
printf("PARENT: %d ",nums[i]); /* LINE Y */
}
这将输出以下内容:
CHILD: 0 CHILD: -1 CHILD: -4 CHILD: -9 CHILD: -16 PARENT: 0 PARENT: 1 PARENT: 2 PARENT: 3 PARENT: 4
因为父进程调用wait()
,所以它会暂停,直到子进程退出。因此孩子的输出首先出现。在孩子退出之后,父母在wait()
电话之后继续,然后打印其输出。