Fork系统调用用于创建一个称为子进程的新进程,该进程与进行fork()调用的进程(父进程)同时运行。创建新的子进程后,两个进程都将在fork()系统调用之后执行下一条指令。子进程使用与父进程相同的pc(程序计数器),相同的CPU寄存器,相同的打开文件。
它不带任何参数,并返回一个整数值。以下是fork()返回的不同值。
负值:创建子进程失败。
零:返回到新创建的子进程。
正值:返回给父级或呼叫者。该值包含新创建的子进程的进程ID。
请注意,以上程序无法在Windows环境下编译。
- 预测以下程序的输出: 。
#include
#include #include int main() { // make two process which run same // program after this instruction fork(); printf("Hello world!\n"); return 0; } 输出:
Hello world! Hello world!
- 计算您好打印的次数:
#include
#include int main() { fork(); fork(); fork(); printf("hello\n"); return 0; } 输出:
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
由第一个分支创建的进程:P1
第二叉创建的进程:P2,P3
第三叉创建的进程:P4,P5,P6,P7P0 / | \ P1 P4 P2 / \ \ P3 P6 P5 / P7
- 预测以下程序的输出:
#include
#include #include void forkexample() { // child process because return value zero if (fork() == 0) printf("Hello from Child!\n"); // parent process because return value non-zero. else printf("Hello from Parent!\n"); } int main() { forkexample(); return 0; } 输出:
1. Hello from Child! Hello from Parent! (or) 2. Hello from Parent! Hello from Child!
在上面的代码中,创建了一个子进程。 fork()在子进程中返回0,在父进程中返回正整数。
在这里,两个输出是可能的,因为父进程和子进程正在同时运行。因此,我们不知道操作系统是先将控制权交给父进程还是子进程。重要说明:父进程和子进程正在运行同一程序,但这并不意味着它们是相同的。 OS为这两个进程分配不同的数据和状态,并且这些进程的控制流可以不同。请参见下一个示例:
- 预测以下程序的输出:
#include
#include #include void forkexample() { int x = 1; if (fork() == 0) printf("Child has x = %d\n", ++x); else printf("Parent has x = %d\n", --x); } int main() { forkexample(); return 0; } 输出:
Parent has x = 0 Child has x = 2 (or) Child has x = 2 Parent has x = 0
在这里,一个进程中的全局变量更改不会影响其他两个进程,因为两个进程的数据/状态不同。而且父级和子级同时运行,因此有两个输出是可能的。
fork()与exec()
fork系统调用将创建一个新进程。 fork()创建的新进程是当前进程的副本,但返回的值除外。 exec()系统调用用新程序替换当前进程。
锻炼:
- 一个进程执行以下代码:
for (i = 0; i < n; i++) fork();
创建的子进程总数为:(GATE-CS-2008)
(一个
(B)2 ^ n – 1
(C)2 ^ n
(D)2 ^(n + 1)– 1;请参阅此解决方案。
- 考虑以下代码片段:
if (fork() == 0) { a = a + 5; printf("%d, %d\n", a, &a); } else { a = a –5; printf("%d, %d\n", a, &a); }
令u,v为父进程打印的值,x,y为子进程打印的值。以下哪一项是TRUE? (GATE-CS-2005)
(A)u = x + 10和v = y
(B)u = x + 10和v!= y
(C)u + 10 = x和v = y
(D)u + 10 = x和v!= y
请参阅此解决方案。 -
预测以下程序的输出。
#include
#include int main() { fork(); fork() && fork() || fork(); fork(); printf("forked\n"); return 0; } 看到这个解决方案
相关文章 :
演示fork()和pipe()的C程序
C语言中的僵尸和孤立进程
fork()和使用它创建的内存共享黑白进程。
参考:
http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html