fork() 函数简介
fork() 函数简介
fork系统调用用于创建一个新进程,称为子进程,它与进行fork()调用的进程(父进程)并发运行。创建新的子进程后,两个进程都将执行fork()系统调用之后的下一条指令。子进程使用相同的PC(程序计数器),相同的CPU寄存器,相同的打开文件,这些文件在父进程中使用。
fork()
它不接受任何参数并返回一个整数值。
下面是fork()返回的不同值。
负值:创建子进程失败。
零:返回到新创建的子进程。
正值:返回给父亲或调用者。该值包含新创建子进程的进程ID。

代码
预测以下程序的运行结果:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
int main()
{
// 在此指令后生成两个运行相同程序的进程
fork(); printf("Hello world!\n");
return 0;
}
运行结果:
Hello world!
Hello world!
计算打印hello的次数。
#include <stdio.h>
#include <sys/types.h>
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 // 一共 7 个子进程,它们中每一个分别创建于这三行中的哪一个呢? L1 // 有 1 个进程创建于Line 1 的fork() P1
/ \
L2 L2 // 有 2 个进程创建于Line 2 的fork() P2~P3
/ \ / \
L3 L3 L3 L3 // 有 4 个进程创建于Line 3 的fork() P4~P7
因此总共有八个进程(新子进程和一个原始进程)。
如果我们想要将进程之间的关系表示为树形层次结构,它将如下所示:
主要进程:p0。
第一个分叉创建的进程:P1。
第二个分叉创建的进程:P2,P3。
第三个分叉创建的进程:P4,P5,P6,P7P0
/ | \
P1 P4 P2
/ \ \
P3 P6 P5
/
P7
预测以下程序的运行结果:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
void forkexample()
{
// 子进程,因为返回值为零
if (fork() == 0)
printf("Hello from Child!\n"); // 父进程,因为返回值非零
else
printf("Hello from Parent!\n");
} int main()
{
forkexample();
return 0;
}
运行结果
1.
Hello from Child!
Hello from Parent!
(或者)
2.
Hello from Parent!
Hello from Child!
解释
在上面的代码中,创建子进程,fork()在子进程中返回0,向父进程返回正整数。
在这里,两个输出是都是有可能的,因为父进程和子进程同时运行。所以我们不知道OS首先把控制权交给哪个进程父进程或子进程。
重要提示:父进程和子进程运行相同的程序,但这并不意味着它们是相同的。OS为这两个进程分配不同的数据和状态,并且控制这些进程的流程也可以不同。请参见下一个示例预测以下程序的运行结果:
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h> 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
(或者)
Child has x = 2
Parent has x = 0
解释
这里,一个进程中的全局变量变化不会影响另外两个进程,因为两个进程的数据/状态不同。而且父进程和子进程同时运行,所以可以有两个输出。
fork() vs exec()
fork系统调用创建一个新进程。fork()创建的新进程是当前进程(返回值除外)的副本。exec()系统调用用新程序替换当前进程。
练习:
一个进程执行以下代码
for (i = 0; i < n; i++)
fork();
创建的子进程总数为:
(A) n
(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是子进程打印的值。下列哪一项是正确的?
(A) u = x + 10 and v = y
(B) u = x + 10 and v != y
(C) u + 10 = x and v = y
(D) u + 10 = x and v != y预测以下程序的输出
#include <stdio.h>
#include <unistd.h>
int main()
{
fork();
fork() && fork() || fork();
fork(); printf("forked\n");
return 0;
}
fork() 函数简介的更多相关文章
- linux进程编程:子进程创建及执行函数简介
linux进程编程:子进程创建及执行函数简介 子进程创建及执行函数有三个: (1)fork();(2)exec();(3)system(); 下面分别做详细介绍.(1)fork() 函数定 ...
- Linux C 中 fork() 函数详解
一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同 ...
- 进程间通信--fork函数
#include <unistd.h> pid_t fork(void); fork() creates a new process by duplicating the calling ...
- Fork函数初识
fork函数用于创建子进程,典型的调用一次,返回两次的函数.其中调用进程返回子进程的PID,而子进程则返回0.但是两个进程的执行顺序是不定的. fork函数调用完成以后父进程的虚拟存储空间被拷贝给了子 ...
- fork()函数详解
原文链接:http://blog.csdn.net/jason314/article/details/5640969 一.fork入门知识 一个进程,包括代码.数据和分配给进程的资源.fork()函 ...
- Linux Shell系列教程之(十五) Shell函数简介
本文是Linux Shell系列教程的第(十五)篇,更多Linux Shell教程请看:Linux Shell系列教程 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高 ...
- fork函数
在Unix/Linux中用fork函数创建一个新的进程.进程是由当前已有进程调用fork函数创建,分叉的进程叫子进程,创建者叫父进程.该函数的特点是调用一次,返回两次,一次是在父进程,一次是在子进程. ...
- Linux—fork函数学习笔记
fork()函数 在赋值语句pid = fork();之前,只有一个进程在执行这段代码,但在这条语句之后,就变成两个进程在执行了,这两个进程的代码部分完全相同.> 两个进程中,原先就存在的那个被 ...
- 【液晶模块系列基础视频】4.5.X-GUI图形界面库-进度条等函数简介
[液晶模块系列基础视频]4.5.X-GUI图形界面库-进度条等函数简介 ============================== 技术论坛:http://www.eeschool.org 博客地址 ...
随机推荐
- 360杯复赛流量分析题 详细writeup
题目名: 这是捕获的黑客攻击数据包 通过分析流量包,得知黑客先上传了一个文件: 追踪TCP流,可以看到文件内容,是一个木马: 然后通过get请求一个加密key,在响应里能看到key的值. 接下来就是用 ...
- Java初级黄金体验 其二
Java初级黄金体验 其二 引言:让我们看一下你的C盘有多少个文件和文件夹 初级 Java IO : 第一个纪念碑 小程序大致功能 让我们看一下E盘有多少个文件 上代码 最近太多的作业 代码可以无限改 ...
- Android Mboot mmc命令介绍
mmc command. 目前Mboot支持以下mmc命令: 1) mmc read/write. 读写命令.Addr = 内存地址, blk# = 起始block数, size ...
- linux设备树编译器DTC【转】
本文转载自:https://blog.csdn.net/chenmiaowu88/article/details/54342823 参考文件: \kernel\Documentation\device ...
- SSIM (Structural SIMilarity) 结构相似性
公式基于样本x和 y 之间的三个比较衡量:亮度 (luminance).对比度 (contrast) 和结构 (structure). 每次计算的时候都从图片上取一个 N*N的窗口,然后不断滑动窗口进 ...
- 小D课堂 - 零基础入门SpringBoot2.X到实战_第5节 SpringBoot部署war项目到tomcat9和启动原理讲解_22、SpringBoot启动方式和部署war项目到tomcat9
笔记 1.SpringBoot启动方式讲解和部署war项目到tomcat9 简介:SpringBoot常见启动方式讲解和部署war项目Tomcat 1.ide启动 2.jar包方式启动 ...
- java泛型--问号?和T或E或K或V的区别
所谓泛型,就是在定义类.接口.方法.参数或成员变量的时候,指定它们操作对象的类型为通用类型. 使用 尖括号 <> 操作符 (The diamond operator )表示泛型, 尖括号内 ...
- 利用 Memory Dump Diagnostic for Java (MDD4J) 分析内存管理问题
利用 Memory Dump Diagnostic for Java (MDD4J) 分析内存管理问题(2) 启动和理解 MDD4J[size=1.0625]为了充分理解如何使用 MDD4J,您需要了 ...
- Dart中的mixins
/* mixins的中文意思是混入,就是在类中混入其他功能. 在Dart中可以使用mixins实现类似多继承的功能,with关键字 因为mixins使用的条件,随着Dart版本一直在变,这里讲的是Da ...
- maven项目新检出后不编译爬坑记 及 mvn clean package报错 WagonTransporterFactory: java.util.NoSuchElementException 异常【我】
从SVN新检出一个maven项目,配置好后,发现项目无法编译(只有一个test包中的代码显示编译报错,其他所有包中的代码都不编译,也不报错), 先注释掉报错的test包中的所有内容, 用Eclipse ...