
本文转自互联网，侵删

本系列文章将整理到我在GitHub上的《Java面试指南》仓库，更多精彩内容请到我的仓库里查看

> https://github.com/h2pl/Java-Tutorial

喜欢的话麻烦点下Star哈

本系列文章将整理到我的个人博客

> www.how2playlife.com

更多Java技术文章会更新在我的微信公众号【Java技术江湖】上，欢迎关注
该系列博文会介绍常见的后端技术，这对后端工程师来说是一种综合能力，我们会逐步了解搜索技术，云计算相关技术、大数据研发等常见的技术喜提，以便让你更完整地了解后端技术栈的全貌，为后续参与分布式应用的开发和学习做好准备。


如果对本系列文章有什么建议，或者是有什么疑问的话，也可以关注公众号【Java技术江湖】联系我，欢迎你参与本系列博文的创作和修订。

<!-- more -->

内核，是指的操作系统内核。

所有的操作系统都有内核，无论是Windows还是Linux，都管理着三个重要的资源：计算，网络，存储。

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230408115530.png)

计算指CPU和内存，网络即网络设备，存储即硬盘之类的。

内核是个大管家，想象你的机器上跑着很多的程序，有word，有excel，看着视频，听着音乐，每个程序都要使用CPU和内存，都要上网，都要存硬盘，如果没有一个大管家管着，大家随便用，就乱了。所以需要管家来协调调度整个资源，谁先用，谁后用，谁用多少，谁放在这里，谁放在那里，都需要管家操心。

所以在这个计算机大家庭里面，管家有着比普通的程序更高的权限，运行在内核态，而其他的普通程序运行在用户态，用户态的程序一旦要申请公共的资源，就需要向管家申请，管家帮它分配好，它才能用。

为了区分内核态和用户态，CPU专门设置四个特权等级0,1,2,3 来做这个事情。

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230408115543.png)

当时写Linux内核的时候，估计大牛们还不知道将来虚拟机会大放异彩，大牛们想，一共两级特权，一个内核态，一个用户态，却有四个等级，好奢侈，好富裕，就敞开了用，内核态运行在第0等级，用户态运行在第3等级，占了两头，太不会过日子了。

大牛们在写Linux内核的时候，如果用户态程序做事情，就将扳手掰到第3等级，一旦要申请使用更多的资源，就需要申请将扳手掰到第0等级，内核才能在高权限访问这些资源，申请完资源，返回到用户态，扳手再掰回去。

这个程序一直非常顺利的运行着，直到虚拟机的出现。

如果大家用过Vmware桌面版，或者Virtualbox桌面版，你可以用这个虚拟化软件创建虚拟机，在虚拟机里面安装一个Linux或者windows，外面的操作系统也可以是Linux或者Windows。

当你使用虚拟机软件的时候，和你的excel一样，都是在你的任务栏里面并排的放着，是一个普通的应用。

当你进入虚拟机的时候，虚拟机里面的excel也是一个普通的应用。

但是当你设身处地的站在虚拟机里面的内核的角度思考一下人生，你就困惑了，我到底个啥？

在硬件上的操作系统来看，我是一个普通的应用，只能运行在用户态。可是大牛们生我的时候，我的每一行代码，都告诉我，我是个内核啊，应该运行在内核态，当虚拟机里面的excel要访问网络的时候，向我请求，我的代码就要努力的去操作网络资源，我努力，但是我做不到，我没有权限！

我分裂了。

虚拟化层，也就是Vmware或者Virtualbox需要帮我解决这个问题。

第一种方式，完全虚拟化，其实就是骗我。虚拟化软件模拟假的CPU，内存，网络，硬盘给我，让我自我感觉良好，终于又像个内核了。

真正的工作模式是这样的。

虚拟机内核：我要在CPU上跑一个指令！

虚拟化软件：没问题，你是内核嘛，可以跑

虚拟化软件转过头去找物理机内核：报告管家，我管理的虚拟机里面的一个要执行一个CPU指令，帮忙来一小段时间空闲的CPU时间，让我代他跑个指令。

物理机内核：你等着，另一个跑着呢。好嘞，他终于跑完了，该你了。

虚拟化软件：我代他跑，终于跑完了，出来结果了

虚拟化软件转头给虚拟机内核：哥们，跑完了，结果是这个，我说你是内核吧，绝对有权限，没问题，下次跑指令找我啊。

虚拟机内核：看来我真的是内核呢。可是哥，好像这点指令跑的有点慢啊。

虚拟化软件：这就不错啦，好几个排着队跑呢。

内存的申请模式如下。

虚拟机内核：我启动需要4G内存，我好分给我上面的应用。

虚拟化软件：没问题，才4G，你是内核嘛，马上申请好。

虚拟化软件转头给物理机内核：报告，管家，我启动了一个虚拟机，需要4G内存，给我4个房间呗。

物理机内核：怎么又一个虚拟机啊，好吧，给你90,91,92,93四个房间。

虚拟化软件转头给虚拟机内核：哥们，内存有了，0,1,2,3这个四个房间都是你的，你看，你是内核嘛，独占资源，从0编号的就是你的。

虚拟机内核：看来我真的是内核啊，能从头开始用。那好，我就在房间2的第三个柜子里面放个东西吧。

虚拟化软件：要放东西啊，没问题。心里想：我查查看，这个虚拟机是90号房间开头的，他要在房间2放东西，那就相当于在房间92放东西。

虚拟化软件转头给物理机内核：报告，管家，我上面的虚拟机要在92号房间的第三个柜子里面放个东西。

好了，说完了CPU和内存的例子，不细说网络和硬盘了，也是类似，都是虚拟化软件模拟一个给虚拟机内核看的，其实啥事儿都需要虚拟化软件转一遍。

这种方式一个坏处，就是慢，往往慢到不能忍受。

于是虚拟化软件想，我能不能不当传话筒，还是要让虚拟机内核正视自己的身份，别说你是内核，你还真喘上了，你不是物理机，你是虚拟机。

但是怎么解决权限等级的问题呢？于是Intel的VT-x和AMD的AMD-V从硬件层面帮上了忙。当初谁让你们这些写内核的大牛用等级这么奢侈，用完了0，就是3，也不省着点用，没办法，只好另起炉灶弄一个新的标志位，表示当前是在虚拟机状态下，还是真正的物理机内核下。

对于虚拟机内核来讲，只要将标志位设为虚拟机状态，则可以直接在CPU上执行大部分的指令，不需要虚拟化软件在中间转述，除非遇到特别敏感的指令，才需要将标志位设为物理机内核态运行，这样大大提高了效率。

所以安装虚拟机的时候，务必要将物理CPU的这个标志位打开，是否打开对于Intel可以查看grep"vmx" /proc/cpuinfo，对于AMD可以查看grep "svm" /proc/cpuinfo

这叫做硬件辅助虚拟化。

另外就是访问网络或者硬盘的时候，为了取得更高的性能，也需要让虚拟机内核加载特殊的驱动，也是让虚拟机内核从代码层面就重新定位自己的身份，不能像访问物理机一样访问网络或者硬盘，而是用一种特殊的方式：我知道我不是物理机内核，我知道我是虚拟机，我没那么高的权限，我很可能和很多虚拟机共享物理资源，所以我要学会排队，我写硬盘其实写的是一个物理机上的文件，那我的写文件的缓存方式是不是可以变一下，我发送网络包，根本就不是发给真正的网络设备，而是给虚拟的设备，我可不可以直接在内存里面拷贝给他，等等等等。

一旦我知道我不是物理机内核，痛定思痛，只好重新认识自己，反而能找出很多方式来优化我的资源访问。

这叫做类虚拟化或者半虚拟化。

如果您想更技术的了解本文背后的原理，请看书《系统虚拟化——原理与实现》

![](https://java-tutorial.oss-cn-shanghai.aliyuncs.com/20230408115552.png)
