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

隔离操作系统与进程

1、隔离操作系统与进程

主要目标就是将原来运行在0x80000000以下init_task_entry移到0x80000000。后续所有的、】非特权级的进程都运行在0x80000000以上。主要分成三部分工作:

1)代码分离

1)将进程first_task的代码与内核代码从文件上分离,但是由于没有文件系统,二者仍然是一同编译的,所以最终汇编出来的文件中,first_task和内核的代码是混在一起的。

2)告诉编译器工具链first_task是运行在虚拟地址0x80000000以上。

因为loader加载内核时,它并不知道first_task的存在,因此无法将first_task的代码正确加载到0x800000000上开始运行。

2)配置加载地址和运行地址

一个程序在编译时,其中的代码和数据等会被划分为一下几块:  .text(放置代码)  .rodata(放置常量)   .data  .bss  还有堆和栈。这些区域的分布,可以通过链接脚本来配置,通过kernel.lds中的配置,可以控制这些代码和数据在内存中应该存在的位置。

GCC编译器在编译工程时,会依据lds中的文件,在生成的ELF文件中包含相应的地址信息(位于program header)

由于first_task 是在kernel.elf中,且加载kernel.elf时,虚拟内存未启用,所以只能和kernel中其它代码一同加载到1MB以下。当first_task运行之前需要将其搬运到0x80000000上运行。因此涉及两个地址:加载地址,运行地址。

对于进程运行,由于其不是从磁盘加载而是从内存加载,需要在运行前,拷贝到指定的虚拟地址空间。另外,在链接脚本中我们可以指定.text / .data等对应的加载地址和运行地址,示例如下

3)搬运代码

在kernel.elf被加载到内存中后,first_task中的所有的代码和数据还只存在于1MB以下的内存中。在运行之前,还需要将其搬却被到0x80000000以上。

为什么不直接让first_task编译成一个独立的可执行程序放在磁盘上运行呢?

这是完全可以的。只不过这里涉及磁盘读取和文件系统的处理,有些复杂。此处并未涉及到这些知识点。

2、调整应用特权级

1)四个权限

从0-3,数值越大,权限越小。操作系统运行于最高权限0,应用程序运行于最低权限3。权限1和权限2可用于运行一引起其它服务

2)与权限相关的配置位

段描述符中的DPL(2位):段描述符中的特权级别,表示一个段的访问权限。值

段选择子RPL(2位):指定当前任务请求的特权级别。

段寄存器CS中的CPL:用于表示当前正在执行的代码的特权级别

DPL、RPL和CPL它的值范围从 03,其中 0 表示最高特权级别(内核模式),3 表示最低特权级别(用户模式)

简化设计:将操作系统的CPL、DPL、RPL全部设置成0,应用程序的全部设置成3

采用权限分离后,会使用分页机制的权限来处理内存访问上的保护。即利用页表中的权限。

页表中的权限配置:

R/W 位(Read/Write):1位,控制页面的可写权限。R/W=0表示页面只读;R/W=1表示页面可读写。

U/S 位(User/Supervisor):1位,控制用户模式(Ring 3)和超级用户模式(Ring 0)对页面的访问权限

因此页表权限设置采用U/S来完成。

3、相应的特权级调整

1)调整异常处理函数

2)修该空闲任务的特权级

由于空闲任务需要执行CPU停机指令HLT,需要较高的权限,需要工作在特权级0下。

具体实现方法是:

在初始化TSS时,根据任务是否是系统任务,设置相应的权限。

int code_sel, data_sel;
if (flag & TASK_FLAG_SYSTEM) {  //判断是否是系统任务code_sel = KERNEL_SELECTOR_CS;data_sel = KERNEL_SELECTOR_DS;
} else {// 注意加了RP3,不然将产生段保护错误code_sel = task_manager.app_code_sel | SEG_RPL3;data_sel = task_manager.app_data_sel | SEG_RPL3;
}

4、特权级切换

1)切换至用户特权级为最低

init_main运行在权限级0的模式下,而first_task需要运行在特权级3,因此这里涉及到从高特权级切换到低特权级的情况。

修改了init_main中的跳转代码,不再采用jmp指令直接跳转到first_task,而是采用iret特权级返回的方式。

由于权限发生了变化,因此栈也发生了变化(硬件自动处理),会有一系列的弹栈过程。

2)为进程添加特权级0的栈空间

应用程序运行时需要使用两种栈:

  • 用于运行应用程序自己代码的特权级3对应的栈,
  • 后续运行系统调用、中断等高特权级0对应的栈

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【源码】IMX6uLL与QT的串口通信
  • 【C++类和对象】类和对象的介绍、this指针以及体会面向对象编程
  • 代码随想录算法训练营第29天 贪心算法 part03| 题目:134. 加油站 、 135. 分发糖果 、860.柠檬水找零 、 406.根据身高重建队列
  • MAC安装miniconda提示“文本编码Unicode(UTF-8)不适用”解决方案
  • uni-app小程序当前页面刷新怎么实现
  • 基于Spring Boot的文字识别系统
  • HarmonyOS开发移动应用:调用百度翻译开放平台的App Id和密钥
  • vue项目中解决el-table数据过多导致页面卡顿问题
  • ZooKeeper 实战(六) - 分布式ID实现方案
  • vue前端获取电脑本机的mac和ip地址
  • Flask+LayUI开发手记(四):弹出层实现增删改查功能
  • (十八)Flink CEP 详解
  • Spring Boot 项目打包及在宝塔面板上部署的简易指南
  • 从C向C++28——设计模式
  • 为什么身边好多公司都开始用加密软件了?
  • [js高手之路]搞清楚面向对象,必须要理解对象在创建过程中的内存表示
  • Bootstrap JS插件Alert源码分析
  • CentOS7 安装JDK
  • Docker: 容器互访的三种方式
  • JavaScript实现分页效果
  • java概述
  • node-sass 安装卡在 node scripts/install.js 解决办法
  • Vim 折腾记
  • 动态魔术使用DBMS_SQL
  • 前端js -- this指向总结。
  • 如何编写一个可升级的智能合约
  • 如何合理的规划jvm性能调优
  • 译米田引理
  • 在electron中实现跨域请求,无需更改服务器端设置
  • ​补​充​经​纬​恒​润​一​面​
  • #NOIP 2014# day.2 T2 寻找道路
  • #数据结构 笔记三
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第5节(封闭类和Final方法)
  • (NSDate) 时间 (time )比较
  • (windows2012共享文件夹和防火墙设置
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)ssm基于jsp的在线点餐系统 毕业设计 111016
  • (几何:六边形面积)编写程序,提示用户输入六边形的边长,然后显示它的面积。
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .Net Core 微服务之Consul(三)-KV存储分布式锁
  • .net mvc 获取url中controller和action
  • .NET 线程 Thread 进程 Process、线程池 pool、Invoke、begininvoke、异步回调
  • .NET成年了,然后呢?
  • .NET开发人员必知的八个网站
  • [ 云计算 | Azure 实践 ] 在 Azure 门户中创建 VM 虚拟机并进行验证
  • [145] 二叉树的后序遍历 js
  • [asp.net core]project.json(2)
  • [BZOJ] 1001: [BeiJing2006]狼抓兔子
  • [C++]spdlog学习
  • [C++]四种方式求解最大子序列求和问题
  • [Editor]Unity Editor类常用方法
  • [flask] flask的基本介绍、flask快速搭建项目并运行