隔离操作系统与进程

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对应的栈

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值