Fork系统调用用于创建一个名为 子进程 ,它与进行fork()调用的进程(父进程)同时运行。创建新的子进程后,两个进程都将执行fork()系统调用之后的下一条指令。子进程使用与父进程相同的pc(程序计数器)、相同的CPU寄存器和相同的打开文件。
它不接受任何参数,并返回一个整数值。下面是fork()返回的不同值。
负值 :创建子进程失败。 零 :返回到新创建的子进程。 正值 :返回给家长或呼叫者。该值包含新创建的子进程的进程ID。
请注意,以上程序不在Windows环境下编译。
- 预测以下程序的输出: .
#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!"
);
return
0;
}
输出:
Hello world! Hello world!
- 计算hello的打印次数:
#include <stdio.h>
#include <sys/types.h>
int
main()
{
fork();
fork();
fork();
printf
(
"hello"
);
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 由第一个fork创建的进程:P1 第二个分支创建的进程:P2、P3 第三个分支创建的流程:P4、P5、P6、P7
P0 / | P1 P4 P2 / P3 P6 P5 / P7
- 预测以下程序的输出:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void
forkexample()
{
// child process because return value zero
if
(fork() == 0)
printf
(
"Hello from Child!"
);
// parent process because return value non-zero.
else
printf
(
"Hello from Parent!"
);
}
int
main()
{
forkexample();
return
0;
}
输出:
1. Hello from Child! Hello from Parent! (or) 2. Hello from Parent! Hello from Child!
在上面的代码中,创建了一个子进程。fork()在子进程中返回0,在父进程中返回正整数。 在这里,两个输出是可能的,因为父进程和子进程同时运行。所以我们不知道操作系统是先控制父进程还是子进程。
重要事项: 父进程和子进程运行相同的程序,但这并不意味着它们是相同的。操作系统为这两个进程分配不同的数据和状态,这些进程的控制流程可能会有所不同。请参见下一个示例:
- 预测以下程序的输出:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void
forkexample()
{
int
x = 1;
if
(fork() == 0)
printf
(
"Child has x = %d"
, ++x);
else
printf
(
"Parent has x = %d"
, --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) (A) n (B) 2^n–1 (C) 2^n (D) 2^(n+1)–1;
看见 这 寻求解决方案。
- 考虑下面的代码片段:
if
(fork() == 0) {
a = a + 5;
printf
(
"%d, %d"
, a, &a);
}
else
{
a = a –5;
printf
(
"%d, %d"
, a, &a);
}
假设u,v是父进程打印的值,x,y是子进程打印的值。以下哪一项是正确的?(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 <stdio.h>
#include <unistd.h>
int
main()
{
fork();
fork() && fork() || fork();
fork();
printf
(
"forked"
);
return
0;
}
看见 这 寻求解决方案
相关文章: C程序演示fork()和pipe() C语言中的僵尸进程和孤儿进程 fork()和使用它创建的内存共享b/w进程。
参考资料: http://www.csl.mtu.edu/cs4411.ck/www/NOTES/process/fork/create.html
本文由 极客队 和 卡丹·帕特尔 .如果你喜欢GeekSforgek,并想贡献自己的力量,你也可以使用 贡献极客。组织 或者把你的文章寄到contribute@geeksforgeeks.org.看到你的文章出现在Geeksforgeks主页上,并帮助其他极客。
如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请写下评论。