`
M_ittrue
  • 浏览: 77770 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

fork函数

 
阅读更多

fork,分叉之意,这是因为其一次调用,两次返回所造成的.先看看一个小程序的执行结果.


 

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
	pid_t pid;
	char *message;
	int n;
	pid = fork();//fork调用
	if (pid < 0) {//调用出错
		perror("fork failed");
		exit(1);
	}
	if (pid == 0) {//子进程返回
		message = "This is the child\n";
		n = 6;
	} else {//pid>0,此时pid是子进程的pid,你进程返回
		message = "This is the parent\n";
		n = 3;
	}
	for(; n > 0; n--) {
		printf(message);
		sleep(1);//休眠1秒,cpu调度切换
	}
	return 0;
}

$ ./a.out 
This is the child
This is the parent
This is the child
This is the parent
This is the child
This is the parent
This is the child
$ This is the child
This is the child

 说明:

由于fork调用,由用户态代换到核心态,父进程产生一个子进程,进程拷贝父进程的相关状态与资源,并生成一个独有的pid标志.

此时父子进程都在核心态等态cpu调度返回,由于不同的cpu调度算法,哪个进程先返回是不一定的,把于输出也是不一样的.

这里是子进程返回,并先输出.但此时sleep(1),1秒对于cpu来说是一个很长的周期,这个时候cpu进行调度,回到使核心态的父进程返回并打印,就是这样周期切换调度创成这样的输出结果.

当最后的父进程结束时,父进程的父进程(shell进程),便输出,但这个时候子进程还没结束,所以子进程直接打印在了shell后.

下面这个图可以看一下这个"分叉"的过程.

fork

 

  1. 父进程初始化。

  2. 父进程调用fork,这是一个系统调用,因此进入内核。

  3. 内核根据父进程复制出一个子进程,父进程和子进程的PCB信息相同,用户态代码和数据也相同。因此,子进程现在的状态看起来和父进程一样,做完了初始化,刚调用了fork进入内核,还没有从内核返回

  4. 现在有两个一模一样的进程看起来都调用了fork进入内核等待从内核返回(实际上fork只调用了一次),此外系统中还有很多别的进程也等待从内核返回。是父进程先返回还是子进程先返回,还是这两个进程都等待,先去调度执行别的进程,这都不一定,取决于内核的调度算法。

  5. 如果某个时刻父进程被调度执行了,从内核返回后就从fork函数返回,保存在变量pid中的返回值是子进程的id,是一个大于0的整数,因此执行下面的else分支,然后执行for循环,打印"This is the parent\n"三次之后终止。

  6. 如果某个时刻子进程被调度执行了,从内核返回后就从fork函数返回,保存在变量pid中的返回值是0,因此执行下面的if (pid == 0)分支,然后执行for循环,打印"This is the child\n"六次之后终止。fork调用把父进程的数据复制一份给子进程,但此后二者互不影响,在这个例子中,fork调用之后父进程和子进程的变量messagen被赋予不同的值,互不影响。

  7. 父进程每打印一条消息就睡眠1秒,这时内核调度别的进程执行,在1秒这么长的间隙里(对于计算机来说1秒很长了)子进程很有可能被调度到。同样地,子进程每打印一条消息就睡眠1秒,在这1秒期间父进程也很有可能被调度到。所以程序运行的结果基本上是父子进程交替打印,但这也不是一定的,取决于系统中其它进程的运行情况和内核的调度算法,如果系统中其它进程非常繁忙则有可能观察到不同的结果。另外,读者也可以把sleep(1);去掉看程序的运行结果如何。

  8. 这个程序是在Shell下运行的,因此Shell进程是父进程的父进程。父进程运行时Shell进程处于等待状态,当父进程终止时Shell进程认为命令执行结束了,于是打印Shell提示符,而事实上子进程这时还没结束,所以子进程的消息打印到了Shell提示符后面。最后光标停在This is the child的下一行,这时用户仍然可以敲命令,即使命令不是紧跟在提示符后面,Shell也能正确读取。

 

    fork函数的特点概括起来就是“调用一次,返回两次”,在父进程中调用一次,在父进程和子进程中各返回一次。从上图可以看出,一开始是一个控制流程,调用fork之后发生了分叉,变成两个控制流程,这也就是“fork”(分叉)这个名字的由来了。子进程中fork的返回值是0,而父进程中fork的返回值则是子进程的id(从根本上说fork是从内核返回的,内核自有办法让父进程和子进程返回不同的值),这样当fork函数返回后,程序员可以根据返回值的不同让父进程和子进程执行不同的代码。

    fork的返回值这样规定是有道理的。fork在子进程中返回0,子进程仍可以调用getpid函数得到自己的进程id,也可以调用getppid函数得到父进程的id。在父进程中用getpid可以得到自己的进程id,然而要想得到子进程的id,只有将fork的返回值记录下来,别无它法。

fork的另一个特性是所有由父进程打开的描述符都被复制到子进程中。父、子进程中相同编号的文件描述符在内核中指向同一个file结构体,也就是说,file结构体的引用计数要增加。

 

   对于父进程pid我们可以用getppid()取得,而自身进程可以用getpid()取得,但子进程只能由返回取得,别无它法.


 

#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc,int *argv[])
{
	pid_t pid;
	char *msg;
	
	int n=0;
	printf("shell pid is %d\n",getppid());
	pid = fork();
	if(pid<0)
	{
		perror("fork failed");
		exit(0);
	}
	if(pid == 0)
	{
		printf("parent pid is %d\n",getppid());
		printf("childhem pid is %d\n",getpid());
		msg = "This is the child\n";
		n = 2;
	}else
	{
		msg = "This is the parent\n";
		printf("shell pid is %d\n",getppid());
		printf("parent pid is %d\n",getpid());
		printf("child pid is %d\n",pid);
		n = 1;
	}
	for(;n>0;n--)
	{
	//	printf(msg);
		//sleep(1);
	}
	return 0;
}
输出;
shell pid is 6279
shell pid is 6279
parent pid is 8669
child pid is 8670
parent pid is 8669
childhem pid is 8670


 

分享到:
评论

相关推荐

    siou005.pdf

    siou005.pdf

    通信考试题库.doc

    通信考试题库.doc

    minecraft-纹理连接图像生成器.py

    minecraft-纹理连接图像生成器.py

    betaflight-1.rar

    betaflight-1.rar

    【Spring Cloud Eureka】微服务注册中心+提供者+消费者完整项目代码|避坑指南+配置注释+一键运行

    包含三大核心模块: Eureka Server:服务注册中心(端口7000) Eureka Provider:服务提供者(端口7006,模拟业务接口) Eureka Consumer:服务消费者(端口7002,集成服务发现与调用) 资源亮点: 完整可运行的Maven项目,开箱即用,避免环境配置踩坑 关键配置逐行注释,新手友好,拒绝“只贴代码不解释” 附赠常见问题解决方案(JDK版本冲突、端口占用、依赖报错) 提供服务调用测试接口,直观验证服务发现效果 适合人群: 初学Spring Cloud微服务的开发者 想快速搭建Eureka Demo的实战派 被版本兼容性问题折磨的“踩坑专业户”

    chromedriver-win64_136.0.7062.0.zip

    chromedriver-win64_136.0.7062.0

    Matlab simulink 风储调频,模糊控制,风电调频,模糊控制改变风电惯性控制系数 储能采用下垂控制 有SOC特性,调频效果好 纯,创新就是模糊控制 模糊控制系数随着风速和频率而改变

    Matlab simulink 风储调频,模糊控制,风电调频,模糊控制改变风电惯性控制系数。 储能采用下垂控制。 有SOC特性,调频效果好。 纯,创新就是模糊控制 模糊控制系数随着风速和频率而改变,实现了自适应控制 mpc主要用于预测频率,3-mpc-模糊控制联合调频,模糊控制结合mpc预测的频率和风速自适应整定调频系数,进而改变调频控制功率。 ,关键词: 1. Matlab Simulink 2. 风储调频 3. 模糊控制 4. 风电调频 5. 虚拟惯性控制系数 6. 下垂控制 7. SOC特性 8. 自适应控制 9. MPC预测 10. 调频系数 以上关键词用分号分隔为:Matlab Simulink;风储调频;模糊控制;风电调频;虚拟惯性控制系数;下垂控制;SOC特性;自适应控制;MPC预测;调频系数。,基于模糊控制与MPC联合调频的风储系统优化研究

    Python全栈一课通视频教程.zip

    目录: 1-1 课程介绍.mp4 1-2 微信小程序点餐项目介绍.mp4 2-1 python介绍.mp4 2-2 Anaconda安装.mp4 2-3 python优缺点介绍.mp4 2-4 hello world程序.mp4 2-5 python的注释.mp4 2-6 变量.mp4 2-7 字符串整数,mp4 2-8 买书案例.mp4 2-9 买书案例改进版本,mp4 2-10格式化输出.mp4 2-11 字符串格式化输出 2-12 python变量的命名规则.mp4 2-13 算数运算符.mp4 2-14 比较运算符.mp4 2-15 逻辑运算符.mp4 2-16 赋值运算符.mp4 2-17 运算符的优先级.mp4 2-18 条件语句入门.mp4 2-19 python代码块.mp4 2-20 条件语句案例.mp4 2-21 节日案例,mp4 2-22 if elif判断成绩案例.mp4 2-23 剪刀石头布游戏.mp4 2-24 while循环 2-25 累加求和 2-26 偶数求和 2-27 break语句 2-28 continue语句 ........ 网盘文件永久链接

    清华大学-DeepSeek从入门到精通

    即将为你照亮探索 DeepSeek 的前行之路,引领你踏入这片充满无限可能的领域

    通信工程建设程序详解南京联通.ppt

    通信工程建设程序详解南京联通.ppt

    数控编程电子教案.doc

    数控编程电子教案.doc

    小学信息技术--计算机基础知识.ppt

    小学信息技术--计算机基础知识.ppt

    复现一篇24年子刊,通过模式匹配筛选指定能带, ,复现; 子刊; 模式匹配; 筛选; 指定能带;,复现子刊24年研究:模式匹配筛选能带分析

    复现一篇24年子刊,通过模式匹配筛选指定能带, ,复现; 子刊; 模式匹配; 筛选; 指定能带;,复现子刊24年研究:模式匹配筛选能带分析

    基于GPS定位的导航地图中多目标位置的预测

    基于GPS定位的导航地图中多目标位置的预测 (论文+MATLAB) 源码

    挑战杯详解-电脑基础知识-IT计算机-专业资料—培训.ppt

    挑战杯详解-电脑基础知识-IT计算机-专业资料—培训.ppt

    MATLAB实现基于NGO-BP北方苍鹰算法优化BP神经网络多输入多输出预测的详细项目实例(含完整的程序,GUI设计和代码详解)

    内容概要:本文档介绍了基于MATLAB实现的NGO-BP(Northern Goshawk Optimization-back propagation,北方苍鹰算法优化BP神经网络)算法优化多输入多输出(MIMO)系统预测的完整项目实例。文档从项目背景与目标出发,详述了项目的挑战及其解决方案,特别强调了NGO算法在全球搜索和局部搜索方面对BP神经网络优化的关键作用。文中还包括项目架构、各模块的设计(如数据预处理、NGO优化、BP网络训练、模型评估与结果输出)、详细源代码示例及图形用户界面(GUI)实现。文档还讨论了项目的应用场景(如工业控制、气象预测、金融风险等),指出了模型的性能优势与改进方向,涵盖了模型更新、大规模数据处理等方面的潜在扩展。 适合人群:熟悉MATLAB编程语言,有一定神经网络基础知识的技术人员,尤其适合从事MIMO系统预测工作的科研工作者或工程师。 使用场景及目标:①适用于需要提升神经网络在多输入多输出系统预测精度和收敛速度的情景,比如智能制造、金融市场分析等领域;②作为学习资料帮助研究人员掌握BP神经网络结合NGO算法的实现过程和技术要点,以推进相关技术的深入研究和发展;③为希望将此类模型部署于生产环境的团队提供从开发到运维全链条的知识指导,如GPU加速、实时数据分析与可视化。 其他说明:文档提供了一整套详细的工程实现方法论,包括但不限于代码细节和GUI设计技巧,并针对可能出现的问题给予了提示和预防措施,如数据预处理的重要性以及超参数的选择等。同时,它也为项目的未来改进预留空间,鼓励采用更多高级技术和跨领域能力提升模型的整体效能,确保其在不断变化的实际环境中保持竞争力。此外,文档也关注到了安全性与用户隐私保护等方面的内容,保证系统的稳健性和合法性。

    java入门 - 数组基础-chapter06.rar

    java入门 - 数组基础-chapter06.rar

    网站建立上传维护.ppt

    网站建立上传维护.ppt

    软考中级冲刺 - 嵌入式系统设计师考点笔记+命题规律+错题溯源实战包+2006-2016真题精解与高频考点全析

    【内容概要】: 本资源囊括软考嵌入式系统设计师全套备考材料,包含:2006-2016年完整真题及专家级答案解析(含解题思路延伸);5套高仿真模拟题(2023新考纲适配版);官方指定教程重点提炼版(精简40%冗余内容);独家整理的「高频考点思维导图」与「错题溯源表」;特别新增RTOS任务调度、CAN总线协议、MMU内存管理等近年高频考点专题解析 【适用人群】: 软考中级备考者;高校计算机专业生;物联网工程师;企业技术培训部。 【使用场景】: 考前3个月系统化复习(每日2小时的学习计划附赠);薄弱环节的专项突破(通过错题率智能诊断表定位);模拟考试环境训练(提供答题卡模板与时间管理策略)。 【数据支撑】: 覆盖近十年98.7%的考点(基于命题数据库分析);2022年真题命中率达83%(对比解析文档验证)。 【差异化优势提炼】: 时效性保障:独家标注2016年后考纲变动对应的历史真题(如AUTOSAR、ROS等新考点);智能备考:提供Excel版「错题-知识点-教材页码」三维映射表;​实战工具:包含考试仿真软件(模拟真实机考环境);增值服务:建立QQ群提供每月专家直播答疑(群号见资源内页)。

    chromedriver-win64_136.0.7054.0.zip

    chromedriver-win64_136.0.7054.0

Global site tag (gtag.js) - Google Analytics