📕
innohub
  • KEEP LEARNING
  • WebInfo
    • JS 部分运算符操作
    • javascript 中的object array
    • 错误处理以及异常捕获
    • JavaScript Bases
    • LaoZi & Confucius
  • PyInfo
    • Python3 输入与输出
    • Python3OS
    • python 修饰器的使用
    • python3 与mysql数据库连接使用实例
    • Format-specifier
    • CGI初学踩坑
    • Django 项目测试
    • Assert-info
    • 使用ngnix和uWSGI配置Django
    • write|SVN​
    • Matplotlib 基本使用
    • 重读 Python 官方文档
    • Python3 Base
    • python3 多线程
    • Python3 函数解析
    • python3 str 对象的基本操作
    • protocl buffers
    • Iterator-Generator
    • Django base
    • Decorator 2
    • Export to wheel or egg-info
    • 三. 运算、数据及逻辑
  • GoInfo
    • Info
      • Select 语句使用
      • First class function
      • Work Pools
      • StructTag
      • Go struct
      • 常用函数
      • Strings操作
      • Golang Bases
      • 数组以及切片
      • 文件操作
      • Golang 中的指针类型
      • Golang Map 类型
      • Reflection
      • 函数闭包
      • 接口
      • Panic and Recover
      • Go中的错误处理
      • 并发
      • defer usage
      • Method in golang
      • Object-oriented Programming
      • Goalng 包管理机制
  • RustInfo
    • Info
      • 包、crate、模块
      • Rust 中的错误处理
      • 智能指针
      • 泛型 generics
      • 数据布局与内存对齐
      • Functions and methods
      • 无畏并发
      • Actix-web 基本使用
      • Got from guessing game
      • 结构体的使用
      • Rust 中的函数式语言功能
      • 集合类型
      • 枚举以及模式匹配
      • Slice 类型
      • 生命周期
      • 测试
      • Rust 中的所有权
      • trait
      • 不安全 Rust
      • Format_print
      • Rust 通用编程概念
      • Macro
  • OS
    • info
      • 内存屏障 -- Part 1
      • 内存屏障 -- Part 2
      • CPU 上下文切换
      • 文件读写与零拷贝
      • ELF 文件
  • MySql
    • info
      • MySql 架构与历史
      • 02-key
  • kubernetes
    • 第二章 k8s 基本概念
    • 第一章 Kubernetes -- 伟大舵手
  • Redis
    • info
      • Redis 总览
      • 02-underline-ds
  • Shell&CInfo
    • GCC 与make的使用
    • C++ 中 malloc 与 new
    • 位运算符操作
    • Base of C macro
    • C 语言中 extern 关键字的用法
  • Distributed
    • info
      • 分布式理论概述
  • Java
    • info
      • Java 内存模型
  • Prometheus
    • Prometheus -- 不灭之火
Powered by GitBook
On this page
  • 1. 什么是cpu上下文
  • 2. 什么是上下文切换
  • 3. 上下文切换类型
  • 3.1 系统调用的上下文切换
  • 3.1 进程上下文切换
  • 3.2 线程上下文切换
  • 3.3 中断上下文切换

Was this helpful?

  1. OS
  2. info

CPU 上下文切换

对于多任务操作系统,支持远大于CPU数量的任务同时运行。操作系统通过给不同的任务划分对应时间片,在用户侧看来,多个任务并发运行。而在每一个任务运行前,cpu都需要知道任务从哪里加载、又从哪里开始运行,需要操作系统预先设置好cpu寄存器以及程序计数器。

1. 什么是cpu上下文

CPU 寄存器和程序计数器就是 CPU 上下文,因为它们都是 CPU 在运行任何任务前,必须的依赖环境。

  • CPU 寄存器是 CPU 内置的容量小、但速度极快的存储部件,可以用来暂存数据、指令、地址;在cpu的控制部件中有指令寄存器(IR)、程序计数器(PC),cpu 的算术以及逻辑部件中包含累加器(ACC)。

  • 程序计数器则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。

2. 什么是上下文切换

把上一个任务的CPU上下文保存下来,然后加载下一个任务的cpu上下文,跳转到新任务的程序计数器,执行新的任务。保存下来的cpu上下文会保存在内核中。在任务重新调度执行时再次加载,保证原任务不受影响。

3. 上下文切换类型

  • 系统调用的上下文切换

  • 进程上下文切换

  • 线程上下文切换

  • 中断上下文切换

3.1 系统调用的上下文切换

Linux 根据特权等,将运行空间划分为内核空间以及用户空间。内核空间具有最高权限,可以管理所有资源,用户空间只能管理受限资源,不能直接访问内存资源,必须通过系统调用陷入内核才能访问特定资源。

由系统调用陷入内核完成从用户态到内核态的转变,这个过程发生的上下文切换:

cpu寄存器的用户态指令位置需要先保存下来,然后加载内核态指令位置,最后跳转到内核态运行任务。系统调用结束后,需要重新回到用户态,恢复用户态上下文。一次系统调用发生两次上下文切换。不过,需要注意的是,系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也不会切换进程。这跟我们通常所说的进程上下文切换是不一样的(系统调用在同一个进程里运行)。 所以系统调用过程通常称为 特权模式切换 ,而不是上下文切换。但实际上,系统调用过程中,CPU 的上下文切换还是无法避免的。

3.1 进程上下文切换

首先进程是由内核管理以及调度的,进程的切换只能发生在内核态。所以进程的上下文切换不仅包括了虚拟内存,栈,全局变量等用户空间的资源,也包括了内核堆栈,寄存器等内核空间的状态。因此进程间上下文切换比系统调用多了一步。在保存当前进程的内核状态以及CPU寄存器之后,需要保存该进程用户空间的虚拟内存,栈等保存下来;在恢复下一个进程的内核态后,需要恢复下一个进程的虚拟内存以及栈。

每次上下文切换需要几十纳秒到数微秒之间。 这个时间还是相当客观的,在高并发场景中,进程下上文切换次数较多,很容易出现大量CPU时间浪费在寄存器,内核栈以及虚拟内存等资源的保存以及恢复上,从而大大减少了进程运行的实际时间。这也是导致系统平均负载升高的原因之一。

进程上下文切换的时机:

  • 进程所分配的时间片耗尽,被系统挂起

  • 系统资源不足时,需要等待资源满足才能运行

  • 进程调用sleep等主动挂起

  • 优先级抢占,更高优先级进程运行,当前进程挂起

  • 发生硬件中断时,cpu上的进程被挂起,运行当前中断服务

3.2 线程上下文切换

线程与进程的一大区别在于,线程是调度的基本单位,进程是资源拥有的基本单位。内核任务的调度对象是线程,而进程只是给线程提供了虚拟内存、全局变量等资源。线程也拥有自己的数据,比如栈以及寄存器,在上下文切换是也需要保存。线程上下文切换分为两种:

  • 不同进程的两个线程,资源不共享,实际上就是进程的上下文切换。

  • 同一进程的两个线程,共享虚拟内存,切换时,只需要切换线程的私有数据、寄存器等。

虽然同为上下文切换,但同进程内的线程切换,要比多进程间的切换消耗更少的资源,这也正是多线程代替多进程的一个优势。

3.3 中断上下文切换

为了快速响应硬件事件,中断处理会打断进程的正常调度和运行,转而调用中断处理程序,响应设备事件。而在打断其他进程时,需要将其运行状态保存下来,在中断结束后可以恢复原进程的执行。

与进程上下文切换不同,中断上下文切换不涉及用户态的操作。所以即使一个中断打断了一个正在用户态处理的进程,陷入内核,也不需要保存和恢复进程的虚拟内存、用户栈等。中断上下文只包括内核态发中断服务所需要的状态:包括cpu寄存器、内核堆栈、硬件中断参数等。在中断程序处理结束后,恢复之前进程的内核态上下文,因为用户态的上下文没有被改变,重置PC后可以继续执行。

对同一个 CPU 来说, 中断处理比进程拥有更高的优先级 ,所以中断上下文切换并不会与进程上下文切换同时发生。同样道理,由于中断会打断正常进程的调度和执行,所以大部分中断处理程序都短小精悍,以便尽可能快的执行结束。

Previous内存屏障 -- Part 2Next文件读写与零拷贝

Last updated 3 years ago

Was this helpful?

kernel-user-ring
trap-context