当前位置: 首页 > news >正文

虚拟地址空间(下)进程地址空间(上)

一.关于页表组成

1.权限(rwx)

作用:如1.让代码区变成只读的 2.写时拷贝的实现:子进程创建时其页表指向的父进程代码和数据权限都是只读的,子进程试图修改,触发错误,系统开始写时拷贝。

来源:1.可执行程序本身已经包含了区域权限信息,代码区不可写等

2.真实地址是否存在的位(isexits)

作用:节省内存空间:

1.分批加载::系统创建进程先加载进程对应磁盘内一部分数据,将页表记录位记录不存在,等进程使用这部分虚拟地址对应的数据时,再从磁盘加载到指定物理地址位置。2.挂起操作。

二.关于mm_struct初始化时怎么分配各区域的大小

1.可执行程序在编译时,各个区域已经确定,直接给mm_struct初始化,(程序内申请空间实质是扩大程序记录的堆的大小(也就是虚拟空间的大小),给mm_struct,操作系统在需要用的时候再开辟空间),执行时mm_struct给操作系统实时开辟

三.进程地址空间(上)

再谈创建进程:

写时拷贝

是什么:创建子进程,子进程实际指向的代码和数据和父进程相同,修改时再拷贝,互不干扰。

实现:创建子进程时,页表所有位置权限位设为只读,一旦子进程和父进程任意一方对共同数据进行写入,触发缺页中断,系统监测是不是需要写时拷贝,是,将数据拷贝一份,修改页表指向,修改权限。互不干扰。

再谈进程终止

1.进程正常退出:看进程退出码判断运行结果是否正常(return 0,return -1...)

2.进程意外终止:OS提前用信号终止了进程(访问非法等)。看退出信号判断情况:退出码为0则没收到信号,退出信号判断进程是否提前退出了,提前退出原因是什么(kill就是给进程信号,退出进程),正常退出了看退出结果是否正确看退出码

再谈进程等待:

回收等待的进程:子进程结束了,就要将退出信号和退出码存入PCB并等待,直到父进程回收

回收系统调用:

pid_t wait(int *status);进程一直等待,直到有它的子进程退出,

接收退出状况status(若不接受可传入空指针),返回退出进程的pid,失败时返回 -1,并设置 errno 以指示错误原因。

pid_t waitpid(pid_t pid,int *status, int options);进程等待一次,若没退出

pid为要等待的子进程(传入-1为任意),options为0为阻塞等待,WNOHANG非阻塞等待

status:

两个判断status情况的宏:bool WIFEXITED(int status)如果进程正常退出则返回真

int WEXITSTATUS(int status).如果正常退出,提取退出码

进程替换

不是创建新进程,是在原进程的基础上替换新的可执行程序的代码和数据(堆栈重新初始化),PCB不换!

创建一个已有可执行程序为基础的进程,可以先创建一个子进程,再进程替换(bash也是这么做的,只需要全部写时拷贝再替换)

补充:

1.readelf -s 可执行程序名

看可执行程序的各个区域大小

2.野指针实质是页表内没有对应映射,操作系统不给访问,运行错误

3.为什么要用虚拟地址空间

-->1.虚拟地址空间+页表保护内存

--->2.让进程以统一视角看物理内存:加载各个区里的物理地址不必连续,虚拟地址连续,进程不必分别管理一块一块。作用:让代码数据可以加载到内存的任意地址处,页表映射寻找效率高O(1)。

---->3.进程管理和内存管理在系统层面解耦合:进程创建只需创建数据结构,其余的代码加载,进程需要的内存操作(申请空间),操作系统可以先骗过进程,等到使用的时候再真进行内存操作。两者具有滞后性,可以更好的省内存,省资源。

4.环境变量为什么一直能被进程看到

进程虚拟地址空间内就有环境变量表

5.1. 打印错误的代码

#include <errno.h>

变量int errno最近函数的错误码,(依赖于最近的函数内是否设置了错误码,fopen,fork都设置了)

#include <string.h>

 char *strerror(int errnum);根据错误码返回错误原因字符串

(标准C库的功能)

5.2. 退出代码

#include<cstdlib>

void exit(int i);让进程直接退出,通过正常退出机制终止进程,设置退出码i。且刷新缓冲区(缓冲区是语言级别的概念,语言编译了维护,不是操作系统的)

_exit(int i);系统调用,退出不刷新缓冲区

exit语言封装了_exit。

6.数据段(Data Segment) 中的数据在 进程创建之前 就已经存在了。具体来说,这些数据是在 程序编译和链接时 确定的,并存储在可执行文件中。当程序启动时,操作系统会加载可执行文件,并将数据段的内容映射到进程的地址空间中。

相关文章:

  • Go语言--安装和环境搭配
  • 地球物理测量学笔记 :分布式声学传感(DAS)
  • linux之 内存管理(1)-armv8 内核启动页表建立过程
  • 【资料分享】通信技术文档汇总(20250319更新)
  • 通过C#脚本更改材质球的参数
  • 集成学习之随机森林
  • 车载以太网网络测试-17【传输层-TCP】
  • 7种寻址方式
  • Elasticsearch 在航空行业:数据管理的游戏规则改变者
  • 蓝桥与力扣刷题(蓝桥 数列求值)
  • 隐私权案件如何办理?公众人物隐私权为何受限?
  • 图莫斯TOOMOSS上位机TCANLINPro使用CAN UDS功能时 编写、加载27服务dll解锁算法文件
  • Spring Framework 中 BeanDefinition 是什么
  • 群体智能优化算法-牛顿-拉夫逊优化算法(Newton-Raphson-Based Optimizer, NRBO,含Matlab源代码)
  • 应用程序安全趋势:左移安全、人工智能和开源恶意软件
  • 物联网为什么用MQTT不用 HTTP 或 UDP?
  • Android14 Log.isLoggable判断的分析
  • C++ 头文件说明
  • 【PCB工艺】基础:电子元器件
  • JAVA-位运算
  • 国内生产、境外“游一圈”再进保税仓,这些“全球购”保健品竟是假进口
  • 上海市政府常务会议研究抓好稳就业稳企业稳市场稳预期工作,让企业感受温度
  • 从世界工厂走向全球创新中心,上海车展为何成为全球汽车行业风向标?
  • 天津外国语大学原校长修刚突发疾病去世,享年68岁
  • 乌称泽连斯基与特朗普进行简短会谈
  • 永辉超市一季度净利降近八成,未来12个月至18个月是改革成果集中释放期