linux中fork()函数的小问题

问题描述:分析下列代码,分别能产生多少a 

//  1
for(int i=0; i<3; i++){
printf("a\n");
fork();
}// 2
for(int i=0; i<3; i++){
fork();
printf("a\n");
}// 3
for(int i=0; i<3; i++){
fork();
printf("a");
}
fflush(stdout);// 4
for(int i=0; i<3; i++){
printf("a");
fork();
}

分析:

【问题1】第0次循环:此时只有p0主进程,直接输出a,然后执行fork();产生一个子进程p1;现在有一个a

        第1次循环:此时有两个进程p0,p1;都输出一个a ,共两个a;然后执行fork();分别产生p2,p3,两个子进程;目前终端输出三个a,有四个进程p0,p1,p2,p3;

        第2次循环:此时四个进程各输出一个 a ;随后产生四个进程,程序结束;终端上一共有1+2+4 = 7 个a。

【问题2】第0次循环:此时只有p0主进程,执行fork(),生成子进程p1,两个进程各自在终端输出一个a,此时终端共两个a;

        第1次循环:此时有p0,p1进程,执行fork(),生成子进程p2,p3,共四个进程,各自输出一个a,此时终端共有 2+4 = 6 个a;

        第2次循环:此时有p0,p1,p2,p3进程,执行fork(),生成四个子进程,共八个子进程,各自在终端输出8个子进程,此时共有 2+ 4+8 = 14个a;

        但是在终端上出现如下情况,原因为各进程间结束时间不一致,当主进程结束时,部分子进程还未结束,会继续向终端输出a;

 此时只要在for循环后加sleep();等待进程全结束即可得到规整的输出:

 void test2(){12     printf("[test2] 预测有 14个\n");13     for(int i=0;i<3;i++){14        fork();15         printf("[test2] : a\n");16     }17 18     sleep(1);                                                                               19 }   

 【问题3】(注:本题以及问题4涉及缓存相关知识)

        第0次循环:主进程p0执行fork()后产生子进程p1,随后执行满缓存输出,此时将a输出当进程p0、p1的缓冲区中,并不直接输出到终端(后两次循环也是一样);

        第1次循环:p0,p1执行fork()后产生p2,p3子进程,随后执行printf(),将a输出到各进程的缓冲区中,此时p0,p1,p2,p3中的缓冲区都存在两个但还未输出;

        第2次循环:同理第1次循环,会产生四个子进程,共八个进程,随后的printf()在各自的进程缓存空间中输出a,当进程结束时,标准输出会刷新缓存,将每个进程中的三个a输出到终端;程序结束后,终端上会显示 3*8 = 24个 a;

 若出现输出在命令行之后的情况,原因同问题2,各个进程结束时间不一致导致,使用sleep()就可以解决。

【4】

        第0次循环:主进程p0执行printf()后并未直接输出,而是将a输出到p0的缓存中。随后执行fork(),产生的子进程p1会复制p0的用户态地址空间;这里有个小知识点fork()采用写时复制,在随后对共享页中i++时候才真正复制p0的栈堆数据等,此时才将p0中的缓存复制一份,这是区别与问题3的;问题3是在各自缓存中加了一个a,问题4是在父进程缓存中先加了一个a,随后复制到各子进程(后两次不作过多赘述,fork()写时复制策略放在最后);此时p0,p1缓存中各有一个a;

        第1次循环:p0,p1执行printf(),将a输出到各进程的缓冲区中,缓存中各自有两个a,执行fork(),产生p2,p3,此时p0,p1,p2,p3中的缓冲区都存在两个a但还未输出;

        第2次循环:同理上次循环,会产生四个子进程,共八个进程,并且在fork()前的printf()在各自的进程缓存空间中输出a,各个进程缓存中存在3个a,当进程结束时,标准输出会刷新缓存,将每个进程中的三个a输出到终端;程序结束后,终端上会显示 3*8 = 24个 a;

 

写时复制

为了减少数据复制的开销, 优化内存管理, fork采用是写时复制(Copy-On-Write,简称COW)的策略

  1. 在fork()执行时,操作系统并不立即复制父进程的整个内存空间给子进程。操作系统使父进程和子进程暂时共享相同的物理内存页。
  2. 这些共享的页面在内存中被标记为只读。如果父进程或子进程尝试写入这些共享的页面(以页为单位),操作系统会为发起写操作的进程(父进程或子进程)分配一个新的物理内存页, 并复制数据到这个页。

写时复制机制确保只有在必要时才复制数据页,这极大地减少了内存使用和提高了效率。

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/80612.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿克曼-幻宇机器人系列教程2- 机器人交互实践(Topic)

在上一篇文章中&#xff0c;我们介绍了两种登录机器人的方式&#xff0c;接下来我们介绍登录机器人之后&#xff0c;我们如何通过topic操作命令实现与机器人的交互。 1. 启动 & 获取topic 在一个终端登录树莓派后&#xff0c;执行下列命令运行机器人 roslaunch huanyu_r…

51c嵌入式~电路~合集27

我自己的原文哦~ 一、7805应用电路 简介 如上图&#xff0c;7805 集成稳压电路。 7805是串联式三端稳压器&#xff0c;三个端口分别是电压输入端&#xff08;IN&#xff09;&#xff0c;地线&#xff08;GND&#xff09;&#xff0c;稳压输出&#xff08;OUT&#xff09;…

Vitrualbox完美显示系统界面(只需三步)

目录 1.使用vitrualbox的增强功能&#xff1a;​编辑 2.安装增强功能&#xff08;安装完后要重启虚拟机&#xff09;&#xff1a; 3. 调整界面尺寸&#xff08;如果一个选项不行的话&#xff0c;就多试试其他不同的百分比&#xff09;&#xff1a; 先看看原来的&#xff0c;…

2025年第十六届蓝桥杯软件赛省赛C/C++大学A组个人解题

文章目录 题目A题目C&#xff1a;抽奖题目D&#xff1a;红黑树题目E&#xff1a;黑客题目F&#xff1a;好串的数目 https://www.dotcpp.com/oj/train/1166/ 题目A 找到第2025个素数 #include <iostream> #include <vector> using namespace std; vector<i…

电机控制储备知识学习(一) 电机驱动的本质分析以及与磁相关的使用场景

目录 电机控制储备知识学习&#xff08;一&#xff09;一、电机驱动的本质分析以及与磁相关的使用场景1&#xff09;电机为什么能够旋转2&#xff09;电磁原理的学习重要性 二、电磁学理论知识1&#xff09;磁场基础知识2&#xff09;反电动势的公式推导 附学习参考网址欢迎大家…

JMeter同步定时器 模拟多用户并发访问场景

同步定时器 JMter同步定时器的作用主要在于模拟多用户并发访问的场景&#xff0c;确保多个线程能够同时执行某个操作&#xff0c;达到真正的并发效果。 当多个线程同时启动时&#xff0c;它们可能会在不同的时间间隔内执行&#xff0c;这样就无法达到真正的并发效果。&#xff…

C++11异步编程 --- async

C11异步编程 — async和future C11引入了async和future机制&#xff0c;用于简化异步编程和并发操作。这两个组件位于<future>头文件中&#xff0c;提供了高级的异步任务管理接口。 一、async 1.定义 std::async std::async是一个函数模板&#xff0c;用于启动一个异…

(七)深度学习---神经网络原理与实现

分类问题回归问题聚类问题各种复杂问题决策树√线性回归√K-means√神经网络√逻辑回归√岭回归密度聚类深度学习√集成学习√Lasso回归谱聚类条件随机场贝叶斯层次聚类隐马尔可夫模型支持向量机高斯混合聚类LDA主题模型 一.神经网络原理概述 二.神经网络的训练方法 三.基于Ker…

[Java实战]Spring Boot 整合 Swagger2 (十六)

[Java实战]Spring Boot 整合 Swagger2 &#xff08;十六&#xff09; 一、Swagger 的价值与痛点 为什么需要 API 文档工具&#xff1f; 开发阶段&#xff1a;前后端高效协作&#xff0c;实时验证接口测试阶段&#xff1a;提供标准化测试用例维护阶段&#xff1a;降低新人理解…

系统稳定性之上线三板斧

&#x1f4d5;我是廖志伟&#xff0c;一名Java开发工程师、《Java项目实战——深入理解大型互联网企业通用技术》&#xff08;基础篇&#xff09;、&#xff08;进阶篇&#xff09;、&#xff08;架构篇&#xff09;清华大学出版社签约作家、Java领域优质创作者、CSDN博客专家、…

题海拾贝:P1833 樱花

Hello大家好&#xff01;很高兴我们又见面啦&#xff01;给生活添点passion&#xff0c;开始今天的编程之路&#xff01; 我的博客&#xff1a;<但凡. 我的专栏&#xff1a;《编程之路》、《数据结构与算法之美》、《题海拾贝》、《C修炼之路》 欢迎点赞&#xff0c;关注&am…

摆脱拖延症的详细计划示例

以下是一个以一周为周期&#xff0c;帮助你摆脱拖延症的详细计划示例&#xff0c;你可以根据自己的实际情况进行调整和完善。 --- # 摆脱拖延症一周计划 ## 一、计划目标 通过一系列有针对性的方法和行动&#xff0c;逐步克服拖延习惯&#xff0c;提高任务执行效率和自我管理…

实物工厂零件画图案例(上)

文章目录 滑台气缸安装板旋转气缸安装板张紧调节块长度调节块双轴气缸安装板步进电机安装板梯形丝杆轴承座 简介&#xff1a;案例点击此处下载&#xff0c;这次的这几个案例并没有很大的难度&#xff0c;练习这几个案例最为重要的一点就是知道&#xff1a;当你拿到一个实物的时…

【Nova UI】十六、打造组件库之滚动条组件(中):探秘滑块的计算逻辑

序言 在上篇文章中&#xff0c;我们完成了滚动条组件开发的前期准备工作&#xff0c;包括理论推导、布局规划和基础设置。现在&#xff0c;我们将把这些准备转化为实际代码&#xff0c;开启滚动条组件的具体开发之旅&#x1f31f;。我们会详细阐述如何实现各项功能&#xff0c…

laravel 使用异步队列,context带的上下文造成反序列化出问题

2025年5月8日17:03:44 如果你是单个应用&#xff0c;异步递交任务&#xff0c;是在应用内部使用&#xff0c;一般不会发生这样的问题 但是现在app项目是 app是一个应用&#xff0c;admin是一个应用&#xff0c;app吧为了接口性能吧异步任务丢给admin去执行&#xff0c;如果两个…

深入剖析 MyBatis 位运算查询:从原理到最佳实践

深入剖析 MyBatis 位运算查询&#xff1a;从原理到最佳实践 引言 在数据库设计中&#xff0c;位运算是一种高效存储和查询多选字段的常用技术。然而&#xff0c;在实际开发中&#xff0c;特别是在使用 MyBatis 这样的 ORM 框架时&#xff0c;位运算查询往往会遇到一些意想不到…

01 | 大模型微调 | 从0学习到实战微调 | AI发展与模型技术介绍

一、导读 作为非AI专业技术开发者&#xff08;我是小小爬虫开发工程师&#x1f60b;&#xff09; 本系列文章将围绕《大模型微调》进行学习&#xff08;也是我个人学习的笔记&#xff0c;所以会持续更新&#xff09;&#xff0c;最后以上手实操模型微调的目的。 (本文如若有…

代码随想录算法训练营第三十八天|动态规划part6(完全背包2)

322. 零钱兑换 题目链接&#xff1a; 322. 零钱兑换 - 力扣&#xff08;LeetCode&#xff09; 文章讲解&#xff1a; 代码随想录 思路&#xff1a; 确定递推公式&#xff1a; dp[j]min(dp[j],dp[j-coins[i]]1); 由于是完全背包 &#xff0c;所以遍历顺序是正序 还存在另一…

使用 ECharts GL 实现交互式 3D 饼图:技术解析与实践

一、效果概览 本文基于 Vue 3 和 ECharts GL&#xff0c;实现了一个具有以下特性的 3D 饼图&#xff1a; 立体视觉效果&#xff1a;通过参数方程构建 3D 扇形与底座动态交互&#xff1a;支持点击选中&#xff08;位移效果&#xff09;和悬停高亮&#xff08;放大效果&#xff…

Transformer Decoder-Only 参数量计算

Transformer 的 Decoder-Only 架构&#xff08;如 GPT 系列模型&#xff09;是当前大语言模型的主流架构&#xff0c;其参数量主要由以下几个部分组成&#xff1a; 嵌入层&#xff08;Embedding Layer&#xff09;自注意力层&#xff08;Self-Attention Layers&#xff09;前馈…