0x1 基础的知识
0x00 OS基础
操作系统本质上是在物理内存中运行的代码+数据
CPU在执行操作系统内核代码的时候,通常运行在高权限环境,拥有完全对硬件访问的能力
CPU在执行用户态的代码是,运行在低权限环境,只有部分/没有硬件访问能力
分级保护域
(hierarchical protection domains) 又称保护环,就是熟知的Rings
在一些硬件或者微代码级别上提供不同特权态模式的 CPU 架构上,保护环通常都是硬件强制的。
Rings是从最高特权级(通常被叫作0级)到最低特权级(通常对应最大的数字)排列的
我们熟知的是Intel的CPU,被分为R0、R1、R2、R3,实际上R1、R2不怎么使用,R0拥有最高权限。
基本上是操作系统内核代码运行在R0。用户进程代码运行在R3。
经 · 典 · 老 · 图 :
运行态切换
操作系统一般用以下两种途径进行特权级的切换
- 中断 :CPU收到一个外部中断时,会切换到R0,并根据中断描述符表索引对应的中断处理代码执行后面的操作。
- 特权级相关指令:R0 -> R3,
iret
指令,R3 -> R0,sysenter
指令。
基于这两种方式,现代操作系统的开发者包装出了系统调用(SYSCALL),作为由“用户态”切换到“内核态”的入口。
用户态:CPU 运行在 ring3 + 用户进程运行环境上下文
内核态:CPU 运行在 ring0 + 内核代码运行环境上下文
当用户进程想要请求更高权限的服务时,便需要通过由系统提供的应用接口,使用系统调用以陷入内核态,再由操作系统完成请求
进程 = 进程运行环境上下文 + 内核数据结构
页表
每个进程都有自己独立的一组页表集
进程调度
使用时钟中断实现的进程调度
具体去看操作系统
进程控制块(PCB,Process Control Block)
0x01 内核种类
介绍
Kernel的主要功能基本能归为以下三点:
- 控制并与硬件进行交互
- 提供应用程序运行环境
- 调度系统资源
与一般的应用程式不同,系统内核的发生 crash 通常会引起系统重启
内核架构:微内核 & 宏内核 & 混合内核
1. 宏内核 (Monolithic Kernel)
宏内核(英语:Monolithic kernel),也译为集成式内核、单体式内核,一种操作系统内核架构,此架构的特性是整个内核程序是一个单一二进制可执行文件,在内核态以监管者模式(Supervisor Mode)来执行。相对于其他类型的操作系统架构,如微内核架构或混合内核架构等,这些内核会定义出一个高阶的虚拟接口,由该接口来涵盖描述整个电脑硬件,这些描述会集合成一组硬件描述用词,有时还会附加一些系统调用,如此可以用一个或多个模块来实现各种操作系统服务,如进程管理、并发(Concurrency)控制、存储器管理等。
from. 维基百科
通俗地说,宏内核几乎将一切都集成到了内核当中,并向上层应用程式提供抽象API(通常是以系统调用的形式),例如 Unix 与类 Unix 便通常都是宏内核
2. 微内核 (Micro Kernel)
在计算机科学中,微内核(英语:Microkernel,μ-kernel),是一种内核的设计架构,由尽可能精简的程序所组成,以实现一个操作系统所需要的最基本功能,包括了底层的寻址空间管理、线程管理、与进程间通信。
from. 维基百科
对于微内核而言,大部分的系统服务(如文件管理等)都被剥离于内核之外,内核仅仅提供最为基本的一些功能:底层的寻址空间管理、线程管理、进程间通信等
0x02 分级保护域
分级保护域(hierarchical protection domains)又被称作保护环,简称 Rings ,是一种将计算机不同的资源划分至不同权限的模型
在一些硬件或者微代码级别上提供不同特权态模式的 CPU 架构上,保护环通常都是硬件强制的。Rings是从最高特权级(通常被叫作0级)到最低特权级(通常对应最大的数字)排列的
在大多数操作系统中,Ring0 拥有最高特权,并且可以和最多的硬件直接交互(比如CPU,内存)
内层ring可以任意调用外层ring的资源
1. Inter环模式
操作系统本身便是一个运行在内核态的程序,当计算机通电之后首先会载入 ROM(BIOS/UEFI),之后载入第二引导程序(Linux 通常用 GNU Grub),由第二引导程序来将操作内核载入到内存当中并跳转到内核入口点,将控制权移交内核
内核在完成一系列的初始化过程之后,会启动一些低权限(ring3)的进程以向我们提供用户界面
2. 虚拟内存空间
在现代操作系统中,计算机的虚拟内存地址空间通常被分为两块——供用户进程使用的用户空间(user space)与供操作系统内核使用的内核空间(kernel space),对于 Linux 而言,通常位于较高虚拟地址的虚拟内存空间被分配给内核使用,而位于较低虚拟地址的虚拟内存空间责备分配给用户进程使用
- 32位
- 64位
3. 用户态 & 内核态
- 用户态:CPU 运行在 ring3 + 用户进程运行环境上下文
- 内核态:CPU 运行在 ring0 + 内核代码运行环境上下文
通常情况下,不同用户进程间的用户地址空间是隔离的,但都共享着相同的内核地址空间,即不同的用户进程在相同的内核虚拟地址空间上都有着一致的对内核物理地址空间的映射
0x03 运行状态切换 & 控制流转移
- 用户进程往往需要使用内核所提供的各种功能,此时就需要通过系统调用等接口陷入内核,待任务完成之后再“着陆”回用户态
- 操作系统往往也需要“主动地”暂停当前进程的运行,让 CPU 陷入到内核态并获取控制权,这通常是因为有需要内核主动处理的事件(如外部中断)
一般来说,CPU由用户陷入到内核态主要有以下几种途径:
- 系统调用 (一般是int 0x80 / syscall / sysenter )
- 异常
- 外设产生中断
用户态 \(\rightarrow\) 内核态:
- 切换GS段寄存器: 通过
swapgs
切换 GS 段寄存器,将 GS 寄存器值和一个特定位置的值进行交换,目的是保存 GS 值,同时将该位置的值作为内核执行时的 GS 值使用 - 保存用户态栈帧信息: 将当前栈顶(用户空间栈顶)记录在 CPU 独占变量区域里(由 GS 寄存器所指定的
percpu
段),将 CPU 独占区域里记录的内核栈顶放入 rsp/esp - 保存用户态寄存器信息: 通过 push 保存各寄存器值到栈上,以便后续“着陆”回用户态
- 通过汇编指令判断是否为32位 (?疑问)
- 控制权转交内核,执行相应的操作
用户态 \(\leftarrow\) 内核态:
swapgs
指令恢复用户态GS寄存器sysretq
或者iretq
系列指令让 CPU 运行模式回到 ring 3,恢复用户空间程序的继续运行
1. 中断
咕咕咕