📅  最后修改于: 2023-12-03 15:15:10.799000             🧑  作者: Mango
Fork 是 C 语言中一个重要的系统调用,它用于创建一个新的进程。新进程和原进程在执行过程中是完全独立的,拥有自己的内存空间与 CPU 时间分配。本篇文章将介绍 Fork 在 C 中的工作原理。
Fork 函数的原型如下:
#include <unistd.h>
pid_t fork(void);
fork() 函数会调用一次,但会返回两次不同的返回值。对于新创建的子进程,fork() 返回 0;而对于原进程,fork() 返回新进程的进程 ID(PID)。
在调用 Fork 函数创建新进程时,操作系统会复制原进程的所有地址空间、代码、数据与内存将它们复制到新进程的地址空间中,同时给新进程分配一个新的 PID。此时,新进程和原进程所执行的代码和数据虽然完全独立,但是在代码和数据的物理存储空间却是共享的。以下是具体的流程:
由于 fork () 返回两次,一次返回新进程的 PID,一次返回 0,因此可以通过返回值来判断当前代码运行在哪个进程中。
以下是一个简单的示例代码,演示了父子进程间的通信和 fork() 返回两次的原理:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main () {
pid_t pid;
int status;
printf("I'm the parent process with PID = %d\n", getpid());
pid = fork();
if (pid == 0) {
printf("I'm the child process with PID = %d\n", getpid());
exit(0);
}
else if (pid > 0) {
printf("I'm the parent process with PID = %d and my child is PID = %d\n", getpid(), pid);
waitpid(pid, &status, 0);
printf("My child process %d terminated with status %d\n", pid, WEXITSTATUS(status));
}
else {
printf("Fork failed!\n");
return 1;
}
printf("Will this line be printed twice by parent and child?\n");
return 0;
}
该程序打印的输出如下:
I'm the parent process with PID = 1234
I'm the child process with PID = 1235
I'm the parent process with PID = 1234 and my child is PID = 1235
My child process 1235 terminated with status 0
Will this line be printed twice by parent and child?
I'm the parent process with PID = 1234
Will this line be printed twice by parent and child?
从上述输出可以看出,程序首先打印 "I'm the parent process with PID = 1234",随后通过 fork() 又创建了一个新的进程,并在其内部打印了 "I'm the child process with PID = 1235"。父进程根据 fork() 返回值区分子进程和父进程,并在两种情况下输出不同的信息。其后,父进程等待了子进程的结束,并打印了相应的进程状态。最后,原始父进程打印了一条语句,并返回到操作系统。
Fork() 是 Linux 操作系统中最常用的系统调用之一。它基于『复制』技术,在创建子进程的同时,将原始进程的数据和代码复制,创建一个几乎完全相同的新进程。新进程和原进程是完全独立的,但又共享一部分物理内存。因此,子进程可以操作父进程内的数据和代码,反之亦然。在程序执行期间,可以使用 getpid () 函数来获取当前进程的 PID,判断代码运行的是哪个进程。