fork()函数详解+示例分析(手工画图+代码图解分析)

最近在学习计算机系统基础这门课程,老师讲到了一个神奇的函数——fork()
所以想在这里总结一下自己对fork()的简单理解

一、首先什么是fork()

fork()函数是通过系统调用 创建一个与原来进程几乎完全相同的进程,两个进程独立存在且可以同时运行(并发),**调用一次,返回两次!**如果初始参数或者传入的变量不同,两个进程也可以做不同的指令。

简单点说,即fork()函数一旦被执行,则该程序就会有两条路可以同时走,先走哪条是不确定的555

在举例子之前,先来了解一下pid:(process id)当前进程的id,程序在父节点处pid>0,在子节点处pid=0,程序出错发生异常时pid=-1。
在这里插入图片描述

二、进入实例练习

1. 小试牛刀,示例1:


int main(){
	pid_t pid;
	int x=1;
	pid=fork();
	if(pid==0){  //child
		printf("child:x=d%\n",++x);
		return 0;
	}
	//parent
	printf("parent:x=d%\n",--x);
	return 0;
} 

输出结果为:
parent:x=0
child:x=2
分析:
程序开始,x初始为1,下一步遇到fork()函数,兵分两路,一路parent,另一路child,当执行parent时,pid>0,输出parent:x=0,当执行child时,pid=0,输出child:x=2
在这里插入图片描述

2、更进一步,实例2

void fork(){
	printf("L0\n");
	fork();
	printf("L1\n")
	fork();
	printf("Bye\n");
} 

可行的一个输出结果为:
L0
L1
Bye
Bye
L1
Bye
Bye
分析:
首先进入程序,输出L0,进入fork()函数,进程一分为二,并发进行,也就是说第一个fork()函数后面的语句要执行两遍,过程图如下
在这里插入图片描述

3、循序渐进、更上一层楼

void fork(){
	printf("L0\n");
	if(fork()!=0){
		printf("L1\n");
		if(fork()!=0){
			printf("L2\n");
		}
	} 
	printf("Bye\n");
} 

可行的一个输出结果为:
L0
L1
Bye
Bye
L2
Bye
分析:
首先进入程序,输出L0,遇到第一个fork(),一条路直接上面的一个Bye,另一条路进入if判断,输出L1,遇到第二个fork,一条路直接到最后一个Bye,另一个输出L2,再输出Bye

在这里插入图片描述

4、 举一反三、牛刀小试,实例4

void doit(){
	printf("he11o\n");
	fork();
	fork();
	return;
}
int main(){
	doit();
	printf("he11o\n");
	exit(0);
}

多少个hello会被打印出来呢?
A、4 B、5 C、6 D、7

来说说你的选择吧,答案解析在文末
5、来来来、接着上

int main(){
	int x=3;
	int y=1;
	if(fork()!=0){
		x=x+y;
		y=y+1;
		printf("x=d%",x);
	}
	x=x+y;
	printf("x=d%",x);
	exit(0);
} 

A、x=4 x=5 x=6
B、x=4 x=5 x=5
C、x=4 x=6 x=6
D、x=4 x=4 x=6
来说说你的选择吧,答案解析在文末

挑战题:
A. 考虑以下 C 程序。假设程序执行完成并且 fork、waitpid 和 printf 总是成功。
在这里插入图片描述
显示此程序的输出:
Child:sum=________
Parent:sum=________
B. 现在考虑与 A 部分相同的程序,但删除了对 waitpid 的调用。假设程序执行完成并且 printf 总是成功。不对其他函数调用的结果做任何假设。
列出此类程序的所有可能输出。每个空白框包含一次程序执行的完整输出。一些空白框可能会被闲置。
在这里插入图片描述
C. 考虑下面的 C 程序。假设程序运行完成并且所有函数都正常返回。
在这里插入图片描述
列出该程序的四种可能输出:





挑战题答案下期给出哟!!!

实例4:答案是5
解析:先调用doit(),打印第一个hello,遇到第一个fork(),第二个的fork要被执行两次,第二个fork本身就需要两次,main函数中的hello被执行了4次
在这里插入图片描述

实例5:答案是D
看图吧,很简单
在这里插入图片描述

### 什么是代码 fork `fork()` 是 Unix 和类 Unix 操作系统中的一个重要系统调用,用于创建一个新的进程。新进程被称为子进程,而原进程则称为父进程。通过 `fork()` 调用,操作系统会复制当前进程的所有资源(包括内存空间、文件描述符等),并为子进程分配独立的 PID[^1]。 当提到 **代码 fork** 的概念时,在软件开发领域还有另一种含义——指开发者从现有的开源项目仓库派生出自己的副本。这种行为常见于 GitHub 或 GitLab 平台上的协作开发场景。例如,ApacheCN 提供了一个 PyTorch 中文文档项目的仓库 https://github.com/apachecn/pytorch-doc-zh ,其他开发者可以对其进行 fork 来获得属于自己的版本以便修改或贡献[^2]。 --- ### 如何进行 fork 操作 #### 方法一:使用 Linux/Unix 系统下的 `fork()` 函数 以下是关于如何在 C 编程语言中实现基本的 `fork()` 功能: ```c #include <stdio.h> #include <unistd.h> int main() { pid_t pid = fork(); // 创建子进程 if (pid == -1) { perror("Fork failed"); return 1; } if (pid == 0) { printf("Child process\n"); // 子进程中执行此部分逻辑 } else { printf("Parent process, child's PID is %d\n", pid); // 父进程中执行该部分逻辑 } while(1); } ``` 上述程序展示了简单的父子进程分离机制。注意每次运行都会打印两行不同的消息分别代表父亲和孩子两个不同身份的过程实例[^4]。 #### 方法二:在线托管平台上的 Fork 操作 对于像 GitHub 这样的平台上完成一个项目的分叉动作非常简单直观: 1. 登录账户访问目标公开存储库页面; 2. 找到右上角按钮点击 “Fork” 即可成功建立自己名下的一份拷贝。 之后按照既定工作流推送更改回原始上游源码树之前先同步最新改动以减少冲突几率[^3]。 --- ###
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LuckyInn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值