Liunx基础-进程概念(下)

2023-11-16

目录

一、程序地址空间

二、fork返回值问题理解


一、程序地址空间

研究背景 kernel 2.6.32 32位平台

程序地址空间回顾

1.地址空间描述的基本空间大小单位是字节

2.32位下-->2^32次方个地址

3.一共有2^32个地址,每个地址标识一个字节,所以能够表示的地址空间范围是2^32*1字节=4GB字节

4.每一个字节都要有唯一的地址,也就需要2^32个地址,即可以用32位的数据表示(00000000~FFFFFFFF)。

区域划分

uint32_t 无符号整型,大小正好32bit

 malloc申请一段mm_struct大小的空间,再将这段空间划分

区域调整

代码区、已初始化、未初始化、全局数据区是固定的,不会变化。但是堆区、栈区是变化的,需要被调整。

 

进程1和进程2都认为自己有2^32个进程地址空间大小,操作系统对进程申请空间有限制。如果进程申请空间超过了限制,操作系统也不允许进程申请。

为什么会存在地址空间:

1. 不安全,如果让进程直接访问物理内存,万一进程越界非法操作呢?肯定会导致数据丢失,或者程序异常。进程直接访问物理内存,可以扫描其他空间存的重要数据。导致机密数据泄露。

2.地址空间的存在,可以更方便的进行进程和进程的数据代码的解耦,保证了进程独立性这样的特征。

3.让进程以统一的视角,来看待进程对应的代码和数据等各个区域,方便使用。编译器也以统一的视角来进行编译代码

 每一个进程因为有页表的存在,页表只会映射到合法内存中。就再也不担心物理内存被写坏、恶意读写。

思考:

我们写的代码出现野指针并不会影响其他程序。

来段代码感受一下

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  5 int g_val = 100;
  7 int main()
  8 {
  9  pid_t id = fork();
 11  if(id < 0)
 12  {
 13   perror("fork error\n");
 14   return 1;
 15  }
 17  else if(id == 0)
 18  { //child
 19    int cnt = 0;
 20    while(1)
 21    {
 22     printf("我是子进程,pid: %-5d, ppid: %-5d | g_val: %d &g_val: %p \n", getpid(),getppid(), g_val,&g_val);
 23     sleep(2);
 30    }
 31  }
 33  else
 34  { //parent
 35    while(1)
 36    {
 37      printf("我是父进程,pid: %-5d, ppid: %-5d | g_val: %d &g_val: %p \n", getpid(),getppid(), g_val,&g_val);                                               
 38      sleep(2);
 39    }
 40  }
 42  return 0;
 43 }

输出

我们发现,输出出来的变量值和地址是一模一样的,很好理解呀,因为子进程按照父进程为模版,父子并没有对变量进行进行任何修改。可是将代码稍加改动: 

  1 #include <stdio.h>
  2 #include <unistd.h>
  3 #include <stdlib.h>
  5 int g_val = 100;
  7 int main()
  8 {
  9  pid_t id = fork();
 11  if(id < 0)
 12  {
 13   perror("fork error\n");
 14   return 1;
 15  }
 17  else if(id == 0)
 18  { //child
 19    int cnt = 0;
 20    while(1)
 21    {
 22     printf("我是子进程,pid: %-5d, ppid: %-5d | g_val: %d &g_val: %p \n", getpid(),getppid(), g_val,&g_val);
 23     sleep(2);
 24     cnt++;
 25     if(cnt == 10)
 26     {
 27       g_val = 300;
 28       printf("子进程已经更改了全局的变量--------------------\n");
 29     }
 30    }
 31  }
 33  else
 34  { //parent
 35    while(1)
 36    {
 37      printf("我是父进程,pid: %-5d, ppid: %-5d | g_val: %d &g_val: %p \n", getpid(),getppid(), g_val,&g_val);                                                                           
 38      sleep(2);
 39    }
 40  }
 42  return 0;
 43 }

输出结果:

我们发现,父子进程,输出地址是一致的,但是变量内容不一样!为什么会这样呢?看图:

进程的地址都是虚拟地址,子进程按照父进程为模版所以地址和父进程一样。当子或者父进程任何一方尝试向共享数据做写入操作,此时操作系统会在物理内存上重新开辟一块空间并将数据拷贝到新空间,修改做操作一方进程的页表的映射关系让它指向新空间。注意,以上图子进程为例修改的是子进程页表左侧,右侧无变化所以我们看到的输出结果&g_val的值没有变。

写时拷贝:

任何一方尝试写入,OS先进行数据拷贝在更改页表映射,然后再让进程进行修改。

进程的独立性

• 独立的内核数据结构

• 写时拷贝--->不同进程的数据进行分离

• 操作系统,为了保证进程的独立性,做了很多的工作!!--->通过地址空间,通过页表让不同进程映射到不同的物理内存处。

分页&虚拟地址空间

说明:

上面的图就足矣说名问题,同一个变量,地址相同,其实是虚拟地址相同,内容不同其实是被映射到了不同的物理地址! 

进一步理解地址空间

让进程以统一的视角,来看待进程对应的代码和数据等各个区域,方便使用。编译器也以统一的视角来进行编译代码

 现有一可执行程序my.exe,由于编译器以统一的视角来进行编译代码,现在程序内部有一套逻辑地址(0x2222、0x1234、0x1122)。———— >程序加载到内存,具备了物理地址。————>操作系统根据逻辑地址和物理地址做映射(页表)。当进程被调度时cpu拿到逻辑地址开始跑,查页表根据映射关系找到物理地址,找到mian函数开始执行。

二、fork返回值问题理解

1. 如何理解fork函数有两个返回值问题?

 

我们知道,当一个函数准备return的时候,核心代码已经执行完了。子进程早已经被创建好了,并且可能在OS的运行队列中,准备被调度了。此时已经有父子进程两个执行流,父进程和子进程各自执行return的。所以有两个返回值。

2.如何理解fork返回之后,给父进程返回子进程pid,给子进程返回0?

父亲:孩子=1:n,n是大于等于1的。一个孩子只有一个父亲,孩子找父亲具有唯一性。fork之后子进程不需要获取父进程的id值。一个父亲有多个孩子,那么怎么确定是哪个孩子呢?所以需要pid来标识子进程。
3.如果理解同一个id值,怎么可能会保存两个不同的值,让if else if同时执行?

返回的本质:就是写入! 所以,父子进程谁先返回,谁就先写入id,因为进程具有独立性,谁先返回,谁就写时拷贝

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Liunx基础-进程概念(下) 的相关文章

  • 通过 SOAP 的 Gmt php 或 UTC C# 等效项

    is C DateTime UtcNow和 PHPdate c 是等价的 我怀疑 因为当我肥皂时 我得到了 C
  • C# 和月历,选择多个日期

    我正在制作一个程序 可以帮助人们用 C 为某个部门 预订 订单 他们需要能够选择不同月份的多个日期 我更愿意拥有它 这样他们就可以单击一个日期 然后按住 Shift 键单击另一个日期以选择这两个日期之间的所有日期 并控制单击以进行单选 取消
  • 如何调整 Windows 窗体以适应任何屏幕分辨率?

    我知道这是重复的问题 但我检查了所有其他相关问题 他们的答案没有帮助 结果仍然与屏幕截图 2 中所示相同 我是 C Windows 窗体新手 如截图1所示 我有Form1有一些控件 每组控件都放在一个面板中 我在 PC1 中设计了应用程序
  • C++中的类要具备什么条件才能成为容器?

    我是 C 编程新手 偶然发现了这个术语containers举例如下vector deque map etc 一个企业的最低要求应该是什么class应该满足被称为container in C 我将从 范围 这个概念开始 Range 只有两个方
  • 具有多个谓词的 C++11 算法

    功能如std find if来自algorithmheader 确实很有用 但对我来说 一个严重的限制是我只能为每次调用使用 1 个谓词count if 例如给定一个像这样的容器std vector我想同时应用相同的迭代find if 多个
  • MSMQ接收和删除

    是否有任何选项可以在读取消息后将其从 MSMQ 中删除 比如 接收 删除可以作为原子操作运行吗 听起来您想查看下一条消息 然后在处理完成后接收它 Message message Queue Peek Queue ReceiveById me
  • 虚拟并行端口模拟器

    在我的计算机网络课程中 我们应该通过使用本机寄存器 例如使用 outportb 等命令 来学习并行端口编程 我没有并行端口 因为我住在 2011 年 但想练习这些程序 我使用 dosbox 安装了旧的 Turboc 3 IDE 有没有一个程
  • 关闭整数的最右边设置位

    我只需要关闭最右边的设置位即可 我的方法是找到最右边位的位置 然后离开该位 我编写这段代码是为了这样做 int POS int n int p 0 while n if n 2 0 p else break n n 2 return p i
  • “没有合适的默认构造函数可用”——为什么会调用默认构造函数?

    我已经查看了与此相关的其他一些问题 但我不明白为什么在我的情况下甚至应该调用默认构造函数 我可以只提供一个默认构造函数 但我想了解它为什么这样做以及它会产生什么影响 error C2512 CubeGeometry no appropria
  • 从点云检测平面集

    我有一组点云 我想测试3D房间中是否有角落 所以我想讨论一下我的方法 以及在速度方面是否有更好的方法 因为我想在手机上测试它 我将尝试使用霍夫变换来检测线 然后我将尝试查看是否有三条线相交 并且它们也形成了两个相交的平面 如果点云数据来自深
  • C 与 C++ 中的 JNI 调用不同?

    所以我有以下使用 Java 本机接口的 C 代码 但是我想将其转换为 C 但不知道如何转换 include
  • 选择 asp.net CheckBoxList 中的所有项目

    ASP NET 和 C 我想要一个带有 全选 项目的复选框列表 当这个特定项目是 已选择 所有其他都将被选择 也 当选择被删除时 这个项目 也将来自所有人 其他物品 选中 取消选中 任何其他项目只会有一个 对特定项目的影响 无论选择状态如何
  • WPF DataGrid - 在每行末尾添加按钮

    我想在数据网格的每一行的末尾添加一个按钮 我找到了以下 xaml 但它将按钮添加到开头 有人知道如何在所有数据绑定列之后添加它吗 这会将按钮添加到开头而不是末尾
  • 将日期时间显示为 MM/dd/yyyy HH:mm 格式 C#

    在数据库中 日期时间以 MM dd yyyy HH mm ss 格式存储 但是 我想以 MM dd yyyy HH mm 格式显示日期时间 我通过使用 String Format 进行了尝试 txtCampaignStartDate Tex
  • 在二进制数据文件的标头中放入什么

    我有一个模拟 可以读取我们创建的大型二进制数据文件 10 到 100 GB 出于速度原因 我们使用二进制 这些文件依赖于系统 是从我们运行的每个系统上的文本文件转换而来的 所以我不关心可移植性 当前的文件是 POD 结构的许多实例 使用 f
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • Unity,c++ 本机插件字节数组不匹配

    在我的 C 本机插件中 我有一个调用 vector
  • IDisposable 的显式实现

    虽然有很多关于IDisposable在 SO 上找到 我还没有找到答案 我通常遵循这样的做法 当我的一个班级拥有一个IDisposable对象然后它也实现IDisposable并打电话Dispose在拥有的对象上 然而最近我遇到了一个类 它
  • 如何在c中断言两个类型相等?

    在 C 中如何断言两种类型相等 在 C 中 我会使用 std is same 但搜索 StackOverflow 和其他地方似乎只能给出 C 和 C 的结果 在C中没有办法做到这一点吗 请注意 这不是询问变量是否具有某种类型 而是询问两个类
  • 是否可以使用 Dapper 流式传输大型 SQL Server 数据库结果集?

    我需要从数据库返回大约 500K 行 请不要问为什么 然后 我需要将这些结果保存为 XML 更紧急 并将该文件通过 ftp 传输到某个神奇的地方 我还需要转换结果集中的每一行 现在 这就是我正在做的事情 TOP 100结果 使用 Dappe

随机推荐

  • Vue全局自定义指令 和 局部自定义指令

    文章目录 自定义指令 Vue全局自定义指令 Vue局部自定义指令 Vue钩子函数 Vue钩子函数传参数详解 钩子函数简写或者合并 自定义指令 除了Vue核心的内置指令 例如 v model 和 v show等 以外 Vue也允许自己定义指令
  • Parsing error Unexpected token错误解决方案

    问题描述 import动态导入 将js文件单独打包时 webpack打包错误 import test then res gt 文件加载成功 console log res mul 2 5 catch gt console log 文件加载失
  • android native 使用opengl es画点线面图形(纯c++)

    一 首先需要对EGL进行初始化 void Renderer initEGL const EGLint attribs EGL SURFACE TYPE EGL WINDOW BIT EGL BLUE SIZE 8 EGL GREEN SIZ
  • Deprecated: __autoload() is deprecated, use spl_autoload_register()

    官网是这样说的 spl autoload register PHP 5 gt 5 1 0 PHP 7 spl autoload register 注册给定的函数作为 autoload 的实现 说明 spl autoload register
  • ply补全为立方体_PLY 文件结构

    典型的 PLY 文件结构 头部 顶点列表 面片列表 其他元素列表 头部是一系列以回车结尾的文本行 用来描述文件的剩余部分 头部包含一个对每个元素类型的描述 包括元素名 如 边 这个元素在工程里有多少 以及一个与这个元素关联的不同属性的列表
  • 第八章 假设检验

    目录 一 假设检验的基本概念 假设及假设检验的定义 原假设与备择假设 基本思想 接受域与拒绝域 假设检验的分类 两类错误 二 一个正态总体下的参数假设检验 期望 方差的假设检验 三 两个正态总体下的参数假设检验 期望的差异性 方差的差异性的
  • 【H5】 svg的 defs用法 渐变

    defs defs元素用于预定义一个元素使其能够在SVG图像中重复使用 在元素中定义的图形不会直接显示在SVG图像上 要显 示它们需要使用元素来引入它们 symbol 元素用于定义可重复使用的符号 嵌入在元素中的图形是不会被直接显示 的 除
  • 前端高频面试题汇总(css,html)

    目录 H5 的新特性有哪些 C3 的新特性有哪些 如何使一个盒子水平垂直居中 如何实现双飞翼 圣杯 布局 CSS 的盒模型 CSS 中选择器的优先级以及 CSS 权重如何计算 列举 5 个以上的 H5 input 元素 type 属性值 C
  • Keil警告warning: #223-D: function “memcpy” declared implicitly

    使用memcpy 函数编译后出现警告 解决方案 在 h文件中加上头文件 include string h
  • GPTzero

    关于GPTzero 网址 https gptzero me 这是我今天才发现的网站 功能是你可以分辨任何人工智能写的文章与人为写的文章 注册方法 注册方法非常简单 只需要一个电子邮箱 我用的是outlook邮箱 其他的也行 使用方法 登录成
  • 【超分辨率】—基于深度学习的图像超分辨率最新进展与趋势

    1 简介 图像超分辨率是计算机视觉和图像处理领域一个非常重要的研究问题 在医疗图像分析 生物特征识别 视频监控与安全等实际场景中有着广泛的应用 随着深度学习技术的发展 基于深度学习的图像超分方法在多个测试任务上 取得了目前最优的性能和效果
  • 我在修改jupyter字体的时候输入命令jt -l 遇到了jt既不是内部也不是外部命令咋整?...

    点击上方 Python爬虫与数据挖掘 进行关注 回复 书籍 即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 独立三边静 轻生一剑知 大家好 我是Python进阶者 一 前言 前几天在Python白银交流群 Joker 问了一
  • 如何在本地快速启动一个k8s集群?小技巧,学到了

    背景 最近在阅读 每天5分钟玩转Kubernetes 这本书 个人感觉是一本不错的 K8S 的入门书籍 我们在刚开始学习一项技术的时候 不论是通过官方文档 书籍 亦或是视频的形式 如果仅仅是去看 而不去练习实践的话 那么是很难将其真正应用起
  • JSTL的错误“attribute test does not accept any expressions”解决方法

    解决方法有2个 1 将 更改为 2 使用JSTL的备用库 将 更改为
  • 数据中台与数据仓库比较

    从三个点来说 1 提供服务的对象 2 业务域 3 层次的划分 1 提供服务的对象 a 数据仓库的服务对象基本上是人 明细数据 聚合指标 转化率模型 他们的目前用户都是人 b 数据中台的服务对象变成 人 机器 用户标签 机器学习模型 数据挖掘
  • 扩展Lucas定理

    本介绍主要是在学习后写下自己的理解 故以转载形式发出 题意 给定 n m p n m p n m p 求 C
  • 个人游戏作品动态图展示

    暗黑破坏神3D战斗手游 2D射击联网对战小游戏 类似以前玩过的4399 联网炸金花游戏 解密类小游戏
  • CRC 在线计算器

    On line CRC calculation and free library https www lammertbies nl comm info crc calculation html
  • warning: ISO C++ forbids converting a string constant to 'char*' [-Wwrite-strings]

    在C 11中有明确规定 char p abc valid in C invalid in C 如果你进行了这样的赋值 那么编译器就会跳出诸如标题的警告 但是如果你改成下面这样就会通过warning char p char abc OK 或者
  • Liunx基础-进程概念(下)

    目录 一 程序地址空间 二 fork返回值问题理解 一 程序地址空间 研究背景 kernel 2 6 32 32位平台 程序地址空间回顾 1 地址空间描述的基本空间大小单位是字节 2 32位下 gt 2 32次方个地址 3 一共有2 32个