从进程开始,搜索和理解进程

Google 搜索关键词: C fork example

什么是fork

Fork系统调用用于创建一个称为子进程的新进程,该子进程与进行fork()调用的进程(父进程)同时运行。

创建新的子进程后,两个进程都将在fork()系统调用之后执行下一条指令。

子进程使用与父进程相同的pc(程序计数器),相同的CPU寄存器,相同的打开文件。

fork返回值

它不带任何参数,并返回一个整数值。以下是fork()返回的不同值。

负值:创建子进程失败。

零:返回到新创建的子进程。

正值:返回给父级或调用者。该值包含新创建的子进程的进程ID。

写点代码

光看上面的解释有点干,来份代码

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{ // make two process which run same
// program after this instruction
fork(); printf("Hello world!\n");
return ;
}

输出:

Hello world!
Hello world!

执行fork函数后,父进程和子进程都会执行下一行代码和后面的代码,所以会输出两遍

计算hello打印的次数

#include <stdio.h>
#include <sys/types.h>
int main()
{
fork();
fork();
fork();
printf("hello\n");
return ;
}

输出

hello
hello
hello
hello
hello
hello
hello
hello

hello打印的次数等于创建的进程数。

进程总数= 2^n,其中n是fork系统调用的数目。所以这里n = 3,2^3 = 8

还不理解?我们来逐行分析

fork ();   // Line 1
fork (); // Line 2
fork (); // Line 3 L1 // There will be 1 child process
/ \ // created by line 1.
L2 L2 // There will be 2 child processes
/ \ / \ // created by line 2
L3 L3 L3 L3 // There will be 4 child processes
// created by line 3

因此,总共有八个进程(新的子进程和一个原始进程)。

如果我们想将流程之间的关系表示为树层次结构,则如下所示:

主进程:P0

第一个fork函数创建的进程:P1

第二个fork函数创建的进程:P2、P3

第三个fork函数创建的进程:P4、P5、P6、P7

预测以下程序的输出

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void forkexample()
{
// child process because return value zero
if (fork() == )
printf("Hello from Child!\n"); // parent process because return value non-zero.
else
printf("Hello from Parent!\n");
}
int main()
{
forkexample();
return ;
}

输出:

.
Hello from Child!
Hello from Parent!
(or)
.
Hello from Parent!
Hello from Child!

在上面的代码中,创建了一个子进程,fork()在该子进程中返回0,并向父进程返回正整数。

在这里,两个输出都是可能的,因为父进程和子进程正在同时运行。 因此,我们不知道操作系统是首先控制父进程还是子进程。

父进程和子进程正在运行同一程序,但这并不意味着它们是相同的。 OS为这两个进程分配不同的数据和状态,并且控制这些进程的流可以有所不同。

看下面的例子:

#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> void forkexample()
{
int x = ; if (fork() == )
printf("Child has x = %d\n", ++x);
else
printf("Parent has x = %d\n", --x);
}
int main()
{
forkexample();
return ;
}

输出:

Parent has x =
Child has x =
(or)
Child has x =
Parent has x =

这里,一个进程中的全局变量更改不会影响其他两个进程,因为两个进程的数据/状态不同。而且父级和子级同时运行,因此有两个输出是可能的。

参考阅读: