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=在子进程中;正=在父进程中(返回值为子进程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
}
子进程与父进程有什么不同?
- 当子进程完成时通过信号通知父进程,反之则不然。
- 孩子不会继承挂起的信号或计时器警报。有关完整列表,请参见fork()
- 这里进程id可以通过getpid()返回。getppid() 可以返回父进程ID。
现在让我们可视化您的程序代码
pid_t pid;
pid = fork();
现在操作系统制作了两个相同的地址空间副本,一个用于父级,另一个用于子级。
父进程和子进程都在系统调用 fork() 之后立即开始执行。由于两个进程具有相同但独立的地址空间,因此在 fork() 调用之前初始化的那些变量在两个地址空间中具有相同的值。每个进程都有自己的地址空间,因此任何修改都将独立于其他进程。如果父进程改变了其变量的值,修改只会影响父进程地址空间中的变量。由 fork() 系统调用创建的其他地址空间不会受到影响,即使它们具有相同的变量名。
这里父 pid 非零,它调用函数 ParentProcess()。另一方面,子进程的 pid 为零,它调用 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
有关更多信息,请参阅此链接