0%

OS Notes Part(III)

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
      • 工作队列
  • Linux 通过request_irq()注册设备的硬中断处理函数

    1
    2
    3
    4
    5
    6
    7
    int request_irq(
    unsigned int irq, // 申请中断号
    iqr_handler_t handler, //中断处理函数
    unsigned long irqflags, //中断类型
    const char* devname, //设备名
    void * dev_id, //设备id
    );

tasklet mechanism

Linux软中断只能在代码编译时静态分配, 无法根据需要进行动态创建, 因此Linux基于软中断了tasklet机制

  • Linuxtasklet结构体的声明

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    enum {
    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/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
      16
      cat /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 number

      1
      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卡)
      • 磁盘(HDDSSD)等
    • 网络设备network device

      • 粒度(处理的数据单位):网络包packet
Linux 设备驱动模型
  • 设备device

  • 驱动driver

  • 总线bus

  • class

Linux 的sysfs文件系统
  • sysfs挂载目录为/sys

    1
    2
    3
    4
    # virtualbox @ virtualbox-VirtualBox in /sys [22:45:56] 
    $ ls
    block bus class dev devices firmware fs hypervisor kernel module power

  • block : 当前系统可用块设备,如【磁盘】和【分区】

  • 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 用户态驱动框架
  1. 避免重构

  2. 规避约束:Linux需要满足GNU的许可证General Public License, GPL,而商用的驱动代码放在用户态方便闭源,如Linux上的NVIDIA驱动

两种Linux用户态驱动框架
  • 用户空间I/OUserspace 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中的inout指令

  • 可虚拟化架构:所有sensitive instruction都是privileged instruction,即所有敏感指令在非特权级下执行都会出发下陷trap

  • 不可虚拟化架构:不满足上定义的架构

  • 弥补不可虚拟化架构缺陷的方法(5种)

    • 解释执行

      • 粒度:单条指令

      • 过程:指令 –> 软件模拟

      • 评估:带来较大的性能开销

    • 动态二进制翻译

      • 粒度:基本块basic block(一段按顺序执行的代码块,中间没有任何改变控制流的指令)

      • 过程:翻译后的basic block成为【代码补丁】,并放置于【代码补丁缓存】中,执行基本块的核心就在于执行代码补丁

      • 评估:批量翻译,缓存

    • 扫描与翻译

      • 过程:(宿主机与虚拟机的【指令集架构ISA (Instruction Set Architecture】相同)只让sensitive instruction下陷,其他指令直接执行
    • 半虚拟化技术

      • 全虚拟化full virtualization:无需修改guest machine源码的方式

      • 半虚拟化para-virtualization:允许修改客户虚拟机源码的方式

        • 超级调用hypercall

          1
          2
          3
          hypervisor 提供-->hypercall--> Virtual Machine
          修改 guest machine 的代码
          --> 替换 [不可虚拟化的指令] 改为超级调用 [hypercall]
        • 优势:

          1. 带来更高性能

          2. 缓解语义鸿沟semantic gap

    • 硬件虚拟化技术

      • x86

        • 根模式root mode和非根模式non-root mode

        • Intel VT-x为每一个虚拟机提供了【虚拟机控制结构VMCS (Virtual Machine Control Structure)

      • ARMv8

        • 增加EL2特权级

        • ARMv8.0的硬件虚拟化中,必须将KVM的一部分功能从Linux中剥离出来,以Lowvisor的形式运行在EL2中,OS和其他KVM功能依然运行在EL1

          1. KVMLowvisor可能有多次特权级转换,带来开销

          2. 为了解决性能和开销问题,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
    4
    1. 静态配置(OS)[VA -PT-> PA] 
    2. 页表安装(OS)[PT base_address->页表基址寄存器]
    3. 动态翻译(MMU)[VA -> PA]
    * PT:Page Table
  • 影子页表使用过程

    1
    2
    3
    4
    5
    6
    1. 静态配置(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

I/O虚拟化

QEMU/KVM

KVM

QEMU