Modern Operating System (III)
- 设备管理
- 系统虚拟化
10 设备管理
- 设备树
device tree文件拓展名为.dts编译生成的二进制文件为.dtb,操作系统启动时kernel通过读取dtb二进制文件获取设备信息 - 通过
MMIO内存映射的方式可以实现CPU对设备的控制,但需要不断【轮询】设备的状态寄存器,效率低下,因此引入【中断】处理机制 - ARM架构在CPU和设备之间引入了【中断控制器
interrupt controller】来管理中断- 优先级
priority - 抢占
preemption
- 优先级
ARMv8中断控制器称为【通用中断控制器Generic Interrupt Controller, GIC】
设备驱动
Interrupt Review
Linux中断处理过程- top half : 完成一些必要但轻量级的工作, 如向中断控制器确认中断
- 硬中断处理函数(又称为中断服务例程
ISR (Interrupt Service Routine)
- 硬中断处理函数(又称为中断服务例程
- bottom half : 完成剩余的、复杂且时延要求较低的操作
- 软中断
- tasklet
- 工作队列
- top half : 完成一些必要但轻量级的工作, 如向中断控制器确认中断
Linux 通过
request_irq()注册设备的硬中断处理函数1
2
3
4
5
6
7int request_irq(
unsigned int irq, // 申请中断号
iqr_handler_t handler, //中断处理函数
unsigned long irqflags, //中断类型
const char* devname, //设备名
void * dev_id, //设备id
);
tasklet mechanism
Linux软中断只能在代码编译时静态分配, 无法根据需要进行动态创建, 因此Linux基于软中断了tasklet机制
Linux中tasklet结构体的声明1
2
3
4
5
6
7
8
9
10
11
12enum {
TASKLET_STATE_SCHED, // 已在kernel注册,可调度
TASKLET_STATE_RUN //当前正在运行
};
struct tasklet_struct {
struct tasklet_struct *next;//链表
unsigned long state;//是否被调度
atomic_t count;//是否被禁用,count>0被禁用;count==0被启动
void (*func)(unsigned long);//回调函数,即被执行的具体函数
unsigned long data;//func的参数
};tasklet机制与softirq区别tasklet允许在运行时动态创建,softirq在代码编译时已经分配好了Linux不允许在多个CPU上并发执行tasklet, 然而Linux允许softirq在多个CPU上并行执行来提升软中断的处理效率, 并且softirq可以被硬中断抢占tasklet依托于中断上下文, 不能睡眠, 不可抢占, 可能引起系统延迟work queue依托于线程上下文, 允许睡眠, 降低了bottom half的开发难度, 同时也关注效率
work queue
work queue把需要推迟的函数,即bottom half, 交给内核线程执行CMWQ (Concurrency Managed WorkQueue): 并发可管理工作队列- 提出线程池
worker-pool, 不同work queue之间可以共享线程池, 从而有效减少了资源浪费和频繁调度
- 提出线程池
设备驱动和设备驱动模型
- 设备驱动
device driver: 操作系统中负责控制设备的定制化程序- 定制化: 驱动本身需要根据设备的具体型号和相应参数进行特定配置
设备驱动模型
OS事先规定好一组【数据结构】和应该实现的【接口】, 然后【驱动开发人员】将【设备驱动】转化为对【数据结构的填充】以及【接口函数的挂在】Linux kernel从2.6版本后引入设备驱动模型
Linux设备抽象
Modern OS : 采用可拓展的结构设计
- 即: OS新功能可以通过新加载的模块来实现, 驱动程序也是这样
Linux 设备抽象
查看内核代码:
- Linux的内核源代码可以从很多途径得到. 一般来讲, 在安装的linux系统下,
/usr/src/linux目录下的东西就是内核源代码。.对于源代码的阅读,要想比较顺利,事先最好对源代码的知识背景有一定的了解.
- Linux的内核源代码可以从很多途径得到. 一般来讲, 在安装的linux系统下,
linux/drivers目录每个子目录基本上代表了一种设备驱动
此处介绍三种基本设备抽象
1.字符设备 2.块设备 3.网络设备
linux/drivers/char–> 字符设备char device- 粒度: 字节
- 字符设备包含了标准的文件操作接口,
open,read,write,close fb(显存),tty(终端),alsa(声卡)major number主设备号,minor number次设备号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16cat /proc/devices
--> 查看Character devices文件系统获取字符设备列表
Character devices:
1 mem
4 /dev/vc/0
4 tty
4 ttyS
5 /dev/tty
5 /dev/console
5 /dev/ptmx
5 ttyprintk
6 lp
7 vcs
...
29 fb
...对于每一个
char device,Linux都会分配一个主设备号major number, 用于识别操作该设备的驱动实体, 一个驱动可能同时操作同类型的多个设备,就会分配一个次设备号minor number1
2
3
4
5$ ls -la /dev/tty /dev/console
crw--w---- 1 root tty 5, 1 7月 7 18:46 /dev/console
crw-rw-rw- 1 root tty 5, 0 7月 7 18:45 /dev/tty
> major number: 5
> minor number: 0, 1块设备
Block Device- 粒度: 块 (设备寻址的最小单元,有512bytes,1KB or 4KB)
ramdisk:虚拟磁盘- 储存卡(
SD卡和MMC卡) - 磁盘(
HDD和SSD)等
网络设备
network device- 粒度(处理的数据单位):网络包
packet
- 粒度(处理的数据单位):网络包
Linux 设备驱动模型
设备
device驱动
driver总线
bus类
class
Linux 的sysfs文件系统
sysfs挂载目录为/sys1
2
3
4# virtualbox @ virtualbox-VirtualBox in /sys [22:45:56]
$ ls
block bus class dev devices firmware fs hypervisor kernel module powerblock : 当前系统可用块设备,如【磁盘】和【分区】
bus:系统中总线(PCI,IDE,USB)连接的物理设备情况
class:当前系统中可用的驱动类型,如【网卡】,【声卡】,【USB设备】
dev:当前系统中字符设备和块设备的主次设备号
devices:系统中已挂载设备的层次化结构
firmware:如x86上的
ACPI等系统固件信息fs:当前系统已挂载的【文件系统信息】
module:当前系统已加载的内核模块,Linux设备驱动均有对应的内核模块
power:电源管理子系统的相关信息
L4设备驱动模型
设备驱动环境
Device Driver Environment, DDE- 复用其他OS上的设备驱动环境
DDE层次
DDEKit
DDE系统环境
原生驱动
Linux 用户态驱动框架
避免重构
规避约束:Linux需要满足GNU的许可证
General Public License, GPL,而商用的驱动代码放在用户态方便闭源,如Linux上的NVIDIA驱动
两种Linux用户态驱动框架
用户空间
I/O,Userspace I/O, UIO虚拟空间
I/O,`Virtual Function I/O, VFIO
11 系统虚拟化
虚拟监控器
VMM (Virtual Machine Monitor),也称为Hypervisor虚拟机
VM (Virtual Machine)基础设施即服务
IaaS (Infrastructure)虚拟机自省
VMI (Virtual Machine Introspection)技术:允许VMM从外部检查虚拟机内部状态是否正确,判断虚拟机是否遭到入寝1
2虚拟机: guest machine
对应物理主机: host machine系统虚拟化技术
系统虚拟化技术
CPU虚拟化
内存虚拟化
I/O虚拟化
虚拟机监控器分类
Hypervisor,又称虚拟机监控器(英语:virtual machine monitor,缩写为VMM),是用来创建与执行虚拟机的软件、固件或硬件。 被hypervisor用来执行一个或多个虚拟机的电脑称为宿主机(host machine),这些虚拟机则称为客户机(guest machine)。
Type-1:Xen
Type-2:Qemu, KVM
CPU虚拟化
下陷和模拟
trap-and-emulate
可虚拟化架构和不可虚拟化架构
指令
特权指令
privileged instruction:在【用户态】执行时会触发下陷trap的指令敏感指令
sensitive instruction:管理物理资源或者更改CPU状态的指令读写特殊寄存器或执行特殊指令以更改CPU状态
读写敏感内存
执行
I/O指令,如x86中的in和out指令
可虚拟化架构:所有
sensitive instruction都是privileged instruction,即所有敏感指令在非特权级下执行都会出发下陷trap不可虚拟化架构:不满足上定义的架构
弥补不可虚拟化架构缺陷的方法(5种)
解释执行
粒度:单条指令
过程:指令 –> 软件模拟
评估:带来较大的性能开销
动态二进制翻译
粒度:基本块
basic block(一段按顺序执行的代码块,中间没有任何改变控制流的指令)过程:翻译后的
basic block成为【代码补丁】,并放置于【代码补丁缓存】中,执行基本块的核心就在于执行代码补丁评估:批量翻译,缓存
扫描与翻译
- 过程:(宿主机与虚拟机的【指令集架构
ISA (Instruction Set Architecture】相同)只让sensitive instruction下陷,其他指令直接执行
- 过程:(宿主机与虚拟机的【指令集架构
半虚拟化技术
全虚拟化
full virtualization:无需修改guest machine源码的方式半虚拟化
para-virtualization:允许修改客户虚拟机源码的方式超级调用
hypercall1
2
3hypervisor 提供-->hypercall--> Virtual Machine
修改 guest machine 的代码
--> 替换 [不可虚拟化的指令] 改为超级调用 [hypercall]优势:
带来更高性能
缓解语义鸿沟
semantic gap
硬件虚拟化技术
x86
根模式
root mode和非根模式non-root modeIntel VT-x为每一个虚拟机提供了【虚拟机控制结构VMCS (Virtual Machine Control Structure)】
ARMv8
增加
EL2特权级在
ARMv8.0的硬件虚拟化中,必须将KVM的一部分功能从Linux中剥离出来,以Lowvisor的形式运行在EL2中,OS和其他KVM功能依然运行在EL1中但
KVM和Lowvisor可能有多次特权级转换,带来开销为了解决性能和开销问题,
ARMv8.1提出VHE (Virtual Host Extension)
1
2
3--> hypercall --> hypercall(maybe)
VM KVM Lowvisor(EL2) Linux and KVM(EL1)
return <-- return <--(maybe)
VHE:可在EL2运行完整的Host Machine系统,KVM进入EL2,其与宿主操作系统Linux之间的交互不会带来任何特权级转换
内存虚拟化
客户虚拟地址
GVA (Guest Virtual Address):进程和客户操作系统使用的虚拟地址客户物理地址
GPA (Guest Physical Address):虚拟机内部使用的物理地址主机物理地址
HPA (Host Physical Address):真正在总线中访问的物理地址1
GVA -第一阶段地址翻译-> GPA -第二阶段地址翻译-> HPA
影子页表
SPT (Shadow Page Table)一般页表使用过程
1
2
3
41. 静态配置(OS)[VA -PT-> PA]
2. 页表安装(OS)[PT base_address->页表基址寄存器]
3. 动态翻译(MMU)[VA -> PA]
* PT:Page Table影子页表使用过程
1
2
3
4
5
61. 静态配置(OS)[GVA -PT-> GPA]
2. 页表安装(OS)[PT base_address->页表基址寄存器]
3. 虚拟机下陷(Hypervisor)[GVA -new PT-> HPA]
4. 页表安装(Hypervisor)[new PT base_address->页表基址寄存器]
3. 动态翻译(MMU)[GVA -> HPA]
* PT:Page Table