【虚拟机】 从 CPU 指令到虚拟机隔离:虚拟机就是一个“模拟了完整硬件的普通进程”

CodeStats | 资深底层技术爱好者与实战派架构师,WWAIC(全周 AI 编程)范式创始人

专注计算机体系结构、操作系统内核、Java 虚拟机实现原理与自研框架落地。本文手撕虚拟机底层:不讲空话,只从 CPU 指令 → 操作系统 → 进程 → 硬件虚拟化这条铁链,彻底讲透虚拟机是什么、凭什么能隔离、和 Docker 容器到底有什么区别。

参考原文(CSDN)从 CPU 指令到容器隔离:Docker 就是一个打了标签的普通进程


📖 本文你能获得什么

程序运行的本质:CPU 取指执行 + 操作系统调度 = 进程的"虚拟 CPU"假象

CPU 权限分级:彻底搞懂 ring 0 / ring 3、内核态/用户态、系统调用

虚拟机执行原理:Guest OS 如何"骗过"CPU ------ 从 Trap & Emulate 到 Intel VT-x 硬件辅助虚拟化

设备模拟真相:硬盘、网卡全是 QEMU 用软件"演"出来的(镜像文件、TAP 设备、virtio)

隔离本质对比:虚拟机隔离"硬件"(独立内核)vs Docker 隔离"名字空间"(共享内核)

技术选型框架:什么时候选虚拟机,什么时候选 Docker,一张表+一句话秒懂

适合谁看:资深底层技术爱好者、实战派架构师、云原生开发者,以及任何想彻底搞懂"虚拟机到底是个什么东西"的人。

目录


核心观点一句话

虚拟机 = 硬件模拟(CPU/内存/硬盘/网卡)+ 独立 Guest OS + 完整隔离边界

它不共享宿主机内核,它是宿主机上一个被赋予了"完整硬件视图"的普通进程。


提问一:程序运行的本质是什么?

程序运行的本质 = CPU 从内存中逐条取指令、执行指令的过程。

一个程序本身只是存放在磁盘上的一组指令和静态数据,没有生命周期。是操作系统把程序代码加载到内存中,生成相应的数据结构(进程控制块、内存映射表等),然后从代码的起始位置读取指令交给 CPU 顺序执行。

CPU 本质上就是一个"去内存中根据地址取指令,然后执行指令的硬件"。指令执行过程中可能遇到跳转指令(循环、条件判断最终都被编译为跳转指令),CPU 的下一条指令就不再是内存中顺序的下一条。

从 CPU → 操作系统 → 应用程序的完整链条是:

层级 职责
CPU 取指、译码、执行,只认机器指令
操作系统 加载程序、调度进程、管理内存、提供系统调用接口
应用程序 在操作系统之上运行,通过系统调用请求内核服务

操作系统提供了"存在多个虚拟 CPU"的假象,让每个进程都以为自己独占整台机器。每个进程被分配一个虚拟地址空间(32 位 Linux 为 4GB),通过 MMU 映射到真实物理内存。


提问二:CPU 权限管控和内核态、用户态是什么关系?

CPU 权限管控 = 通过指令集特权级划分,将操作系统和用户程序运行在不同权限级别上。

Intel x86 CPU 用 ring 0(内核态)ring 3(用户态) 来划分权限:

运行态 特权级 能力
内核态 (Ring 0) 最高 可执行任何 CPU 指令,直接操作硬件,访问所有内存地址
用户态 (Ring 3) 最低 只能执行受限指令,访问受限资源,不能直接访问硬件

内核态和用户态的关系:

有一类指令叫特权指令 (如读写硬盘、修改内存映射表),一旦用错,整个操作系统会直接宕机。因此,普通程序要访问硬件,必须通过系统调用(System Call)陷入内核,让内核代劳。

当用户态程序发起系统调用时,CPU 会从 ring 3 切换到 ring 0,跳转到内核代码位置执行,完成后再从 ring 0 返回 ring 3。

这一层奠定了"权限分级控制"的基础。


提问三:虚拟机是如何通过用户态进程执行内核态权限指令的?

核心答案:通过「Trap & Emulate」(陷阱+模拟)或「硬件辅助虚拟化」技术。

虚拟机(如 KVM + QEMU)本身是宿主机上的一个用户态进程,但 Guest OS 内部有自己的内核态和用户态。问题在于:Guest OS 认为自己运行在 ring 0,但实际它在宿主机上只是一个用户态进程,没有真正的 ring 0 权限。

解决方案有两种:

1. 纯软件模拟(Trap & Emulate)

当 Guest OS 执行一条特权指令时,由于它实际运行在用户态,CPU 会触发一个陷阱(Trap) ,陷入宿主机内核。宿主机内核(或 VMM)捕获这个陷阱后,模拟执行这条指令,然后把结果返回给 Guest OS。

这种方式叫"陷阱-模拟"------敏感指令被捕获,由软件模拟执行。

缺点是性能差:每条特权指令都要触发陷阱、陷入内核、模拟执行、返回。

2. 硬件辅助虚拟化(Intel VT-x / AMD-V)

现代 CPU 提供了专门的虚拟化指令集(Intel VT-x、AMD-V)。KVM 利用这些硬件能力,让 Guest OS 的指令直接在 CPU 上运行,不需要软件模拟。

工作流程如下:

  1. 用户态的 QEMU 通过 ioctl 系统调用进入 KVM 内核模块
  2. KVM 为虚拟机创建虚拟 CPU(vCPU)虚拟内存
  3. 执行 VMLAUNCH 指令,CPU 进入客户模式(Guest Mode)
  4. Guest OS 在客户模式下直接运行,大部分指令由硬件直接执行
  5. 遇到敏感操作时,CPU 自动退出客户模式,由 KVM 处理

一句话总结:虚拟机不是"在用户态执行内核指令",而是通过硬件虚拟化扩展,让 Guest OS 运行在一个特殊的"客户模式"下,敏感指令由 VMM 捕获并模拟。


提问四:虚拟机是如何解决硬盘和网卡模拟的?

核心答案:通过「设备模拟」------在虚拟机监控器(VMM)中用软件模拟硬件设备的行为。

虚拟机需要让 Guest OS 认为自己有真实的硬盘和网卡。但实际上,这些都是软件模拟出来的。

硬盘模拟

在宿主机上创建一个镜像文件 (如 .qcow2.raw),作为虚拟磁盘。当 Guest OS 发起磁盘 I/O 请求时:

  1. Guest OS 的驱动程序向"虚拟硬盘"发出读写指令
  2. 这些指令被 VMM(如 QEMU)捕获
  3. QEMU 将指令转换为对宿主机镜像文件的读写操作
  4. 结果返回给 Guest OS

网卡模拟

类似地,QEMU 模拟一个标准的网卡设备(如 Intel e1000)。Guest OS 看到的是一块真实的物理网卡,实际上所有网络数据包都由 QEMU 处理:

  1. Guest OS 发送数据包到"虚拟网卡"
  2. QEMU 捕获数据包
  3. QEMU 通过宿主机的网络栈(如 TAP 设备、网桥)将数据包发出
  4. 收到的数据包由 QEMU 注入到 Guest OS 的"虚拟网卡"

I/O 虚拟化的三种方式

方式 原理 性能
设备模拟(全虚拟化) 纯软件模拟硬件设备 最低
半虚拟化(virtio) Guest OS 知道自己被虚拟化,与 VMM 协作 较高
设备直通(PCI Passthrough) 直接将物理设备分配给虚拟机 最高

一句话总结:硬盘和网卡的模拟,本质是 VMM 在宿主机上"假装"成硬件设备,拦截 Guest OS 的 I/O 请求并转换为对宿主机资源的操作。


提问五:虚拟机隔离的本质是什么?一句话总结

虚拟机隔离的本质 = 通过 VMM(虚拟机监控程序)在硬件层面模拟出多台独立的"物理机器",每台虚拟机拥有独立的 CPU、内存、硬盘、网卡和操作系统内核,彼此之间完全不可见、不可访问。

一台虚拟机的崩溃(操作系统故障、应用程序崩溃、驱动程序故障)不会影响同一物理服务器上的其他虚拟机。每个虚拟机都像运行在独立的物理机器上一样。

虚拟机的隔离是硬件级别的强隔离,因为它模拟的是完整的硬件边界。


提问六:虚拟机和 Docker 区别对比及各场景一句话总结

对比表格

维度 虚拟机(KVM) 容器(Docker)
隔离边界 硬件(模拟完整硬件) 内核(系统调用接口)
独立内核 每个虚拟机一个 Guest OS 内核 无,共享宿主机内核
启动时间 分钟级 毫秒级
资源开销 GB 级别 MB/KB 级别
隔离级别 强(硬件辅助虚拟化) 中(内核 Namespace)
本质 模拟硬件,跑操作系统 隔离进程,跑应用

各场景一句话总结

场景 一句话推荐
需要运行不同内核的操作系统(如在 Linux 上跑 Windows) 选虚拟机,因为容器共享宿主机内核,无法运行不同内核的 OS
多租户环境、遗留应用迁移、强安全隔离要求 选虚拟机,硬件级隔离更彻底
微服务架构、云原生应用、快速弹性伸缩 选 Docker,轻量快速,资源利用率极高
快速开发、测试和部署,大规模应用分发 选 Docker,秒级启动,镜像分层复用
传统 IT 环境中的服务器虚拟化项目 选虚拟机,成熟稳定,隔离性好
混合部署(需要兼顾隔离和效率) 两者结合:在虚拟机中运行多个 Docker 容器

本质升华:一台机器 vs 一个进程

纵观全文,从CPU指令到设备模拟,虚拟机和Docker给出了两种截然不同的"隔离"答卷:

  • 虚拟机(KVM)的隔离思想是"向下切割硬件" :它通过VMM在物理硬件层面 模拟出独立的CPU、内存、硬盘和网卡,每一台虚拟机都拥有自己独立的操作系统内核。虚拟机本质是在硬件边界上筑墙------墙内系统崩溃(如内核Panic),墙外宿主机和其他虚拟机毫无感知。这是一种**"物理机器级"的强隔离**,重资产,但绝对彻底。

  • Docker容器的隔离思想是"向上圈定进程" :它不模拟任何硬件,而是利用Linux内核的命名空间(Namespace)操作系统层面 给进程打上"视野标签"(独立的PID、网络、文件系统等),再用Cgroups划定资源使用上限。Docker本质是在操作系统边界上画圈------所有容器共享宿主机同一个内核,隔离的是"进程能看到什么、能用多少资源",而非硬件本身。这是一种**"进程级"的轻量隔离**,快如闪电,但共享内核风险。

一句话记住它们

虚拟机隔离的是"硬件" ,所以它能跑Windows也能跑Linux,不依赖宿主机内核,防的是"物理故障和内核崩溃"

Docker隔离的是"操作系统名字空间" ,所以它只能跑与宿主机同内核的应用,防的是"进程干扰和文件冲突"

思想终极提炼

  • 虚拟机的核心思想"把一台物理主机,变成多台虚拟主机" ------ 解决的是"硬件资源池化与多系统共存"问题。
  • Docker的核心思想"把一台物理主机上的进程,安排得明明白白" ------ 解决的是"应用交付与环境依赖一致性"问题。

在技术选型的天平上:

  • 如果你担心内核级漏洞 或需要运行异构OS,请把砝码压在虚拟机(硬件墙)上;
  • 如果你追求极致弹性微服务迭代资源利用率,请把砝码压在Docker(进程标签)上。

记住:虚拟机动的是"地基"(硬件),Docker改的是"门牌号"(命名空间)。地基隔开的是整栋楼,门牌号隔开的是同一栋楼里的不同房间。


最后:点赞 · 收藏 · 评论

如果这篇文章帮你彻底搞懂了虚拟机的底层原理,并理清了它与Docker的本质区别:

  • 👍 点赞 让更多同学看到这篇硬核推演
  • ⭐ 收藏 方便随时复习完整逻辑链
  • 💬 评论 留下疑问或补充

从 CPU 指令到硬件虚拟化,从硬件墙到命名空间标签------你已掌握云计算虚拟化技术的两大基石。


© 2026 CodeStats | 原创不易,转载注明出处

相关推荐
慧一居士1 小时前
SpringCloud 微服务Feigin 用的完整调用端和被调用的示例
java·spring cloud
我命由我123452 小时前
Jetpack Room - Room 查询返回列表无需判空、LIKE 关键字
android·java·开发语言·java-ee·android jetpack·android-studio·android runtime
平安的平安2 小时前
传统Java工程师第一次用飞算JavaAI生成SpringBoot项目
java
csjane10792 小时前
Redisson 限流原理
java·redis
一个做软件开发的牛马2 小时前
MyBatis 从零实战:完整搭建可运行 Demo,注解与 XML 双模式开发详解
java·后端
用户298698530142 小时前
Java 实践:查找与提取 Word 文档超链接
java·后端
Flittly2 小时前
【AgentScope Java新手村系列】(9)SpringBoot集成
java·spring boot·spring
星环科技2 小时前
数据标准Agent ,让企业数据说同一种语言
java·开发语言·前端
SimonKing2 小时前
Qoder 提供免费 Qwen3.7-Max,无需订阅
java·后端·程序员