内核,是指的操作系统内核。
所有的操作系统都有内核,无论是Windows还是Linux,都管理着三个重要的资源:计算,网络,存储。
计算指CPU和内存,网络即网络设备,存储即硬盘之类的。
内核是个大管家,想象你的机器上跑着很多的程序,有word,有excel,看着视频,听着音乐,每个程序都要使用CPU和内存,都要上网,都要存硬盘,如果没有一个大管家管着,大家随便用,就乱了。所以需要管家来协调调度整个资源,谁先用,谁后用,谁用多少,谁放在这里,谁放在那里,都需要管家操心。
所以在这个计算机大家庭里面,管家有着比普通的程序更高的权限,运行在内核态,而其他的普通程序运行在用户态,用户态的程序一旦要申请公共的资源,就需要向管家申请,管家帮它分配好,它才能用。
为了区分内核态和用户态,CPU专门设置四个特权等级0,1,2,3 来做这个事情。
当时写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
这叫做硬件辅助虚拟化。
另外就是访问网络或者硬盘的时候,为了取得更高的性能,也需要让虚拟机内核加载特殊的驱动,也是让虚拟机内核从代码层面就重新定位自己的身份,不能像访问物理机一样访问网络或者硬盘,而是用一种特殊的方式:我知道我不是物理机内核,我知道我是虚拟机,我没那么高的权限,我很可能和很多虚拟机共享物理资源,所以我要学会排队,我写硬盘其实写的是一个物理机上的文件,那我的写文件的缓存方式是不是可以变一下,我发送网络包,根本就不是发给真正的网络设备,而是给虚拟的设备,我可不可以直接在内存里面拷贝给他,等等等等。
一旦我知道我不是物理机内核,痛定思痛,只好重新认识自己,反而能找出很多方式来优化我的资源访问。
这叫做类虚拟化或者半虚拟化。
如果您想更技术的了解本文背后的原理,请看书《系统虚拟化——原理与实现》
微信公众号
个人公众号:程序员黄小斜
微信公众号【程序员黄小斜】新生代青年聚集地,程序员成长充电站。作者黄小斜,职业是阿里程序员,身份是斜杠青年,希望和更多的程序员交朋友,一起进步和成长!这一次,我们一起出发。
关注公众号后回复“2019”领取我这两年整理的学习资料,涵盖自学编程、求职面试、算法刷题、Java技术、计算机基础和考研等8000G资料合集。
技术公众号:Java技术江湖
微信公众号【Java技术江湖】一位阿里 Java 工程师的技术小站,专注于 Java 相关技术:SSM、SpringBoot、MySQL、分布式、中间件、集群、Linux、网络、多线程,偶尔讲点Docker、ELK,同时也分享技术干货和学习经验,致力于Java全栈开发!
关注公众号后回复“PDF”即可领取200+页的《Java工程师面试指南》强烈推荐,几乎涵盖所有Java工程师必知必会的知识点。