fork函数详解

前言

之前我们提到,创建子进程的时候,需要使用fork()函数,其中分别有id ==0和id >0的if函数,但是实验表明,两个if函数中的内容都得到了实现。按照我们之前所学,一个变量同一时间只能有一个值,那到底是怎么满足两个if都实现的呢?

1. fork函数

1.1 返回值:

fork函数在运行的时候创建新进程,新进程是子进程,旧进程是父进程。

fork函数的返回值:

>0:父进程,具体的数字是子进程的pid

==0:子进程

<0:出错

证明:

#include<stdio.h>
#include<unistd.h>
int main()
{pid_t id = fork();if(id==0){printf("我是子进程");printf("mypid:%d,myppid:%d\n",getpid(),getppid());printf("%p\n",&id);id = 5;//	printf("%p\n",&id);//	printf("%d\n",id);}else if(id>0){printf("我是父进程");printf("mypid:%d,myppid:%d\n",getpid(),getppid());printf("%p\n",&id);if(id==id){printf("1\n");}}return 0;
}

这里就能看出,子进程和父进程的关系以及>0的具体数字。

1.2 进程执行过程

当子进程创建后,会存在两个二进制代码相同的进程,分别是子进程和父进程,此时子进程中的数据和父进程的数据是相同的。因为子进程的创建是为了执行和父进程不同的任务,那么就避免不了对父进程的数据进行更改,那么此时操作系统就会给子进程重新开辟一块空间,存储子进程自己修改的数据,而未被修改的数据,就还是和父进程用一样的。这便是写时拷贝。

写时拷贝:等到修改数据时才真正分配内存空间,这是对程序性能的优化,可以延迟甚至是避免内存拷贝,当然目的就是避免不必要的内存拷贝。

1.3 页表

知道了进程执行过程,但是我们好像还是没有解决为什么id会有两个值同时出现的问题。

通过在父进程和子进程中分别打印id的地址,我们知道他们的地址是一样的。

但是我们知道,物理地址对应的数据是唯一的,那么我们拿到的地址就肯定不是物理地址。

因此此时打印的地址是虚拟地址。

这是因为页表的存在。

页表中存在着虚拟地址,物理地址,以及标记位(如进程对应的代码和数据是否已经加入到内存中),访问权限等。

如果没有加载到内存当中,那么就会触发缺页中断。即暂停进程执行,直到进程的数据和代码加载到内存中。

为什么会有缺页中断呢?因为CPU加载数据时是采用的惰性加载方式,当需要的时候才进行加载。这样能避免造成内存浪费。

其中虚拟地址和物理地址存在映射的关系。我们需要通过虚拟地址访问物理地址。

需要注意的是,写时拷贝并不影响虚拟地址,只会改变其映射的物理地址。

页表的作用:

1. 让所有进程能以统一角度看待内存。(让进程不必知道具体的物理地址)

2.让非法命令不能直接到达物理地址

3. 由于程序地址空间和页表的存在,将进程管理模块和内存管理模块进行解耦合(独立性)

即进程管理模块只需要使用虚拟地址,不用关心物理地址。

此时的进程 =内核(tast_struct + mm_struct)+数据和代码 。

mm_struct存储程序地址空间。

页表的首地址存储在CPU内存中的一个CR3寄存器中,此寄存器属于进程的上下文,当切换进程时,会带走该数据。

切换进程时还要切换程序地址空间,而pcb指向程序地址空间。

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

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

相关文章

OkHttp网络请求框架

添加依赖 在 build.gradle 文件中添加 OkHttp 依赖&#xff1a; dependencies {implementation("com.squareup.okhttp3:okhttp:4.10.0") }使用OkHttp发起GET请求 同步请求 public class MainActivity extends AppCompatActivity {// Used to load the okhttptes…

Ue5 umg学习(三)文本控件

从通用中&#xff0c;选择文本控件 将其拉入画布中&#xff0c;和图像控件使用方法类似。 右边是字形&#xff0c;尺寸&#xff0c;字间距。 可以导入字形&#xff0c;使用&#xff0c;不过要注意&#xff0c;不要导入FZ系字体&#xff0c;不然可能会涉及侵权 修改尺寸会修…

希冀 实验五 请求分页式存储管理

void FIFO_solve() { memset(in, 0, sizeof(in)); int fault_n 0; //缺页次数 int ptr, i; //预调页填满内存 ptr 0; //下一个要存放的位置 for (i 0; i < maxn && ptr < size; i) if (!in[page[i]]) { pin[…

终于弄懂了Python变量的作用域:局部变量与全局变量

Python变量的作用域&#xff1a;局部变量与全局变量 在Python编程中&#xff0c;作用域指的是变量在程序中的可见性或访问范围。作用域的概念决定了变量可以在程序的哪些地方被访问和修改。理解变量的作用域&#xff0c;特别是局部变量和全局变量之间的差异&#xff0c;对编写…

wireshark演进之路——从GTK到Qt

Wireshark 自 1998 年诞生至今&#xff0c;已有超过26年的历史了。它最早由 Gerald Combs 创建&#xff0c;最初名为 Ethereal。2006 年&#xff0c;Ethereal 更名为 Wireshark&#xff0c;并继续发展成了全球领先且人尽皆知的网络协议分析工具&#xff0c;其GUI演变就是其中非…

OpenGL 进阶系列07 - 阴影贴图(shadowmap )

一:概述: 在 OpenGL 中,Shadow Mapping(阴影贴图)是一种常用的实时阴影技术,用于渲染物体的阴影效果。这种方法通过生成光源视角下的深度贴图,再在场景渲染时使用它来判断物体是否被遮挡,从而实现阴影效果。下面是实现 Shadow Mapping 的基本步骤和相关知识。 二:绘制…

el-form el-table 前端排序+校验+行编辑

一、页面 <template><div class="bg" v-if="formData.mouldData?.length == 0">当前暂无模板,点击<view class="add" @click="addMould">立即创建</view></div><div v-else><el-col :xs=&…

【大数据学习 | HBASE高级】rowkey的设计,hbase的预分区和压缩

1. rowkey的设计 ​ RowKey可以是任意字符串&#xff0c;最大长度64KB&#xff0c;实际应用中一般为10~100bytes&#xff0c;字典顺序排序&#xff0c;rowkey的设计至关重要&#xff0c;会影响region分布&#xff0c;如果rowkey设计不合理还会出现region写热点等一系列问题。 …

html实体字符

HTML 实体字符 HTML 实体字符&#xff08;HTML Entities&#xff09;是在 HTML 中用来表示那些在 HTML 文档中直接使用可能会引起问题的特殊字符的一种方法。这些特殊字符包括但不限于尖括号、与号、引号等&#xff0c;它们在 HTML 中有特定的用途&#xff08;如标签界定符、属…

CSS Modules中的 :global

最近写需求遇到如下代码&#xff0c;我们来分析一番&#xff1a; .medicine-bot {:global(.cosd-site-vcard-card) {margin-top: -3px;}:global(.cosd-site-vcard-title-text) {font-size: var(--cos-text-headline-sm);}:global(.cosd-site-vcard-button) {background-color: …

JavaWeb后端开发案例——苍穹外卖day01

day1遇到问题&#xff1a; 1.前端界面打不开&#xff0c;把nginx.conf文件中localhost:80改成81即可 2.前后端联调时&#xff0c;前端登录没反应&#xff0c;application.yml中默认用的8080端口被占用&#xff0c;就改用了8081端口&#xff0c;修改的时候需要改两个地方&…

Centos7镜像下载与docker安装

注意&#xff1a; CentOS 7 已于2024年6月30日停止维护&#xff01; 1、下载 由于 centos 7 已经停止维护&#xff0c;部分镜像网站移除了对centos 7的支持&#xff0c;这里找到了部分现在还可以使用的镜像网站 阿里云开源镜像站&#xff1a;https://mirrors.aliyun.com/cent…

科技云报到:数字化转型,从不确定性到确定性的关键路径

科技云报到原创。 数字化转型是VUCA时代最大的确定性。 如果说&#xff0c;过去是数字化转型的试验阶段&#xff0c;实施的是开荒动土、选种育苗&#xff0c;那么当前要进行的是精耕细作、植树造林&#xff0c;数字化转型已进入了由个别行业、个别场景的“点状应用”向各行各业…

AgentReview:基于 LLM Agents 模拟同行评审过程的框架

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…

如何查看电脑关机时间

要查看电脑的关机时间&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. 打开事件查看器&#xff1a;按下键盘上的Windows键R键&#xff0c;然后在弹出的运行对话框中输入"eventvwr.msc"&#xff0c;并按下Enter键。 2. 在事件查看器窗口中&#xff0c;单击左侧窗…

详解Gemini API的使用:在国内实现大模型对话与目标检测教程

摘要&#xff1a;本博客介绍了如何利用Gemini API实现多轮对话和图像目标检测识别功能&#xff0c;在Python中快速搭建自己的大模型完成实际任务。通过详细的步骤解析&#xff0c;介绍了如何申请Gemini API密钥&#xff0c;调用API、对话实现的代码&#xff0c;给出了上传图片识…

java操作ES(一)RestHighLevelClient(2)集成与demo

一、集成方法 1、pom依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.x.x</version> <!-- 请使用与你的Elasticsearch版本相匹配的版…

HashMap的put流程知道吗

HashMap 的 put 方法算是 HashMap 中比较核心的功能了&#xff0c;复杂程度高但是算法巧妙&#xff0c;同时在上一版本的基础之上优化了存储结构&#xff0c;从链表逐步进化成了红黑树&#xff0c;以满足存取性能上的需要。本文逐行分析了 put 方法的执行流程&#xff0c;重点放…

5. ARM_指令集

概述 分类 汇编中的符号&#xff1a; 指令&#xff1a;能够编译生成一条32位机器码&#xff0c;并且能被处理器识别和执行伪指令&#xff1a;本身不是指令&#xff0c;编译器可以将其替换成若干条指令伪操作&#xff1a;不会生成指令&#xff0c;只是在编译阶段告诉编译器怎…

uniapp的基本使用(easycom规范和条件编译)和uview组件的安装和使用

文章目录 1、uniapp1.uview组件安装2.uview-plus组件安装 2、条件编译3、easycom规范1.组件路径符合规范2.自定义easycom配置的示例 总结 1、uniapp UniApp的UI组件库&#xff0c;如TMUI、uViewUI、FirstUI、TuniaoUI、ThorUI等&#xff0c;这些组件库适用于Vue3和TypeScript&…