-
2020-03-05 19:37:54
一、发送端创建共享区域,并写入内容:
//1 先删除之前创建的 shared_memory_object::remove("MySharedMemory_Name"); //2 创建共享内存段 shared_memory_object shm(create_only, "MySharedMemory_Name", read_write); //3 设置共享内存大小 shm.truncate(100); //4 映射共享内存片段 mapped_region region(shm, read_write); //5 初始化为0 std::memset(region.get_address(), 0, region.get_size()); //6 往内存里写入数据 string *strTest = static_cast<string*>(region.get_address()); *strTest = "hello world";
二、另一个进程读取内存
//1 读取共享内存 shared_memory_object shm(open_only, "MySharedMemory_Name", read_only); //2 映射共享内存 mapped_region region(shm, read_only); //3 检查共享内存是否被初始化为1 string* strRead = static_cast<string*>(region.get_address());
更多相关内容 -
Ubuntu系统下多进程的共享内存使用
2018-11-25 01:01:35在查阅了大量例程后,发现共享内存的建立一般有两种,一种是使用shmget()函数,另一种是使用shmopen()。大致的说一下两种建立方法的流程。 shmget() 首先先申请内存大小,之后在将id和地址位置进行映射,即: ...前言
作为一个刚刚完成研究生阶段学习初入职场的小白菜,而且还是从机械电子工程专业转到软件工程师这样一个小的转行,在刚刚进行工作的3个月,犹如填鸭式的学习了很多之前写代码并不会用到的功能。在碰到的很多问题之后,就上百度搜索应该怎么解决,发现基本都是在CSDN上有很多现成的解决办法,并且也能给很多启发。因此,在实际上解决了问题之后,希望能够记录下一些问题的出现的原因,以及相应的我所解决问题的办法。开始慢慢写这类博客吧,一方面是记录一下成长的过程,另一方面也是希望能够给以后同样碰到这类问题的人有个启示吧。目前碰到的都是一些很基础的问题,大神勿喷。(话说这个博客编辑界面和shareLaTeX好像啊)
多进程的建立
多进程的建立在这就简单的说一下,就是使用fork函数。
pid_t pid;
pid=fork();
if(pid<0){
子进程创建失败
}
if(pid==0){
子进程运行程序
}else{
父进程运行程序
}
就是一个很基本的fork()函数运用,并没有碰到啥问题,也就不展开说了。共享内存的建立
在查阅了大量例程后,发现共享内存的建立一般有两种,一种是使用shmget()函数,另一种是使用shmopen()。大致的说一下两种建立方法的流程。
- shmget()
首先先申请内存大小,之后在将id和地址位置进行映射,即:
shmget()->shmat()
图片来自于百度百科。
第一个参数key_t key我觉得就相当于一个标识,相当于给这块共享内存的唯一代号。我使用的就是一个简单的强制类型转换,例如(key_t)1234。当然在寻找例程以及解决之后要说的问题的过程中,发现在创建key的过程中有些需要注意的点,而且为了唯一性,同样可以在这个位置填写IPC_PRIVATE。
第二个参数就是设置共享内存的大小。这里就是我之后要说的问题的关键点了。第一次申请的共享内存的大小决定了他的上限,并且只要你没有进行过删除这段共享内存的操作,这段共享内存会一直存在。要想申请这段共享内存成功需要确认几点:内存大小比能申请的最小值大且比最大值小,若以该键值申请过共享内存了,之后所申请的内存大小要比第一次开的内存大小要只小不大。
第三个参数就模式标志了,这个在上图中已经解释的很清楚了。
当完成了shmget之后,例如:
int shmid;
shmid=shmget((key_t)1234, 4096,0666|IPC_CREAT|IPC_EXCL);
if(shmid==-1){
//创建失败,该共享内存已存在
shmid=shmget((key_t)1234,4096,0666|IPC_CREAT);
if(shmid==-1){
perror("share memory creat failed. ");
exit(EXIT_FAILURE);
}
}
perror会打印出上一个错误发生的原因。原因的描述如上图所示。
在得到id之后,就需要将id和内存地址进行相互映射了,这个操作就是使用shmat()
上图来自百度百科
可以指定地址,也可以让内核自己决定一个合适的地址位置,建立如下:
void shm = NULL;
shm=shmat(shmid, (void) 0 ,0);
if(shm==(void*)-1){
perror(“shmat failed”);
exit(EXIT_FAILURE);
}
这样就完成了共享内存的建立以及映射了。
之后就可以通过memcpy,strcpy等等方法将需要写进共享空间的内容写进去。- shmopen()
在项目中,并没有用这个方法去建立共享内存,那也就给一个相关的例程:
https://blog.csdn.net/maopig/article/details/16920907
这个因为没有研究使用过,就不详细说了。
问题产生
我目前这个项目,需要一个进程连续不断的读取数据,数据的上传速度差不多是1000Hz,需要另一个进程对得到的数据进行处理。每一次的数据处理需要有一定的数据量,比如说需要有300个数据,才能进行一次的数据处理。本来想尝试单进程的,但是发现单进程的话数据实时性有很大的问题,因此最后决定使用多进程。因为之前是学习机电的,就算是要写软件写的是单片机的裸机程序,连线程的概念都很薄弱更别说多进程了,因此就直接硬着头皮上了。然后就发现在开共享内存空间的时候,这个内存大小怎么都开不大,每一次在size那个参数里写比较大的数,程序就进判断,然后exit with failure了。本来以为是因为系统设置的问题,上网查了一下怎么去看系统的允许的最大最小共享内存大小值。
这里插一句,要插看共享内存能开的最大最小值的命令是:
cat /proc/sys/kernel/shmmax
cat /proc/sys/kernel/shmmni
然后发现最小值是4096,最大值是18446744073692774399
我需要开的内存大小也就是10k左右,比最大值小得多,在范围里啊,怎么就申请不了呢?然后就是不停地上网搜原因。最后根据shmget()函数的机理,终于明白是怎么回事了。问题解决
会出现这个问题,是因为,我以一个键值已经申请过一块共享内存了,在第一次做这个操作的时候,开的内存很小大概就255,就这一下决定了这块内存空间的上限,之后再想要加大这块内存空间就是不可能的事情了,除非换一个键值。
通过命令 ipcs -m去查看我内存管理,果然是有一块已申请的内存空间。那就只能把这个内存给删除了。
可以直接通过命令行去删除
ipcrm -m id号
这样之后再申请共享内存的时候就不会报错了结论
没有学习过相关的内容,这样摸着石头过河,真的是心累啊。不过好歹还有点资料以及前人的经验可以借鉴。
- shmget()
-
Kubernetes中Pod间共享内存方案
2019-02-21 17:30:00在高并发业务下,尤其还是以C/C++代码实现的基础组件,经常会使用共享内存通信机制来追求高性能,本文给出了Kubernetes Pod间Posix/SystemV共享内存方式的折中方案,以牺牲一定的安全性为代价,请知悉。当然,如果...转载本文需注明出处:微信公众号EAWorld,违者必究。
摘要:
一些公共服务组件在追求性能过程中,与业务耦合太紧,造成在制作基础镜像时,都会把这些基础组件都打包进去,因此当业务镜像启动后,容器里面一大堆进程,这让Kubernetes对Pod的管理存在很大隐患。为了让业务容器瘦身,更是为了基础组件自身的管理更独立和方便,将基础组件从业务镜像中剥离并DaemonSet容器化部署。然而一些基础组件Agent与业务Pod之间通过共享内存的方式进行通信,同一Node中跨Pod的共享内存方案是首先要解决的问题。
目录:
一、为什么要将公共基础组件Agent进行DaemonSet部署
二、Linux共享内存机制
三、同一Node上夸Pod的共享内存方案
四、灰度上线
一、为什么要将公共基础组件Agent进行DaemonSet部署自研的公共基础组件,比如服务路由组件、安全组件等,通常以进程方式部署在Node上并同时为Node上所有的业务提供服务,微服务及容器化之后,服务数量成百上千的增长,如果以sidecar或者打包到业务Image中继续Per Pod Per Agent的方式部署, 那么基础组件的Server端的压力可能也会成百上千的增长,风险是很大的。因此,我们希望能以DaemonSet方式部署这些组件的Agents。
先说说Kubernetes大行其道的今天,如果不将这些基础组件从业务Pod中剥离,存在哪些问题:
业务容器中存在一大堆进程,我们在为Pod申请资源(cpu/mem request and limit)时,不仅要考虑业务应用本身的资源消耗,还要考虑这些基础组件的资源消耗。而且一旦某些Agent有Bug,比如内存泄漏,这将导致Pod牵连被重建,甚至Cgroup OOM在kill进程时,可能将业务进程kill了。
违背了Kubernetes&微服务的部署最佳实践:Per Process Per Contaienr,并且业务进程在前台运行,使其与容器共生死,不然这将导致Kubernetes无法根据业务进程状态关联到容器状态,进而进行高可用管理。
一个Node上运行10个Pod,那么就会有x10的基础组件数量在Node上。没有容器化之前,一个Node只要部署一个组件进程即可,容器化之后,集群中组件Agents数量要几十倍的增长,如果业务进行了微服务拆分,这个指数会更大,这些基础组件服务端是否能承受比以往高几十倍上百倍的通信请求,这是未知的。
如果你要全网升级某个基础组件Agent,那你可能会疯掉,你需要重新打所有业务镜像,然后全网业务要进行灰度升级。因为一个Agent的升级,导致你不得不重建业务Pod。你可能会说,基础组件Agents都会有自己的热升级方案,我们通过它们的方案升级就好了呀,那你将引入很大麻烦:Agents的热升级因为无法被Kubernetes感知,将引发Kubernetes中集群中的数据不一致问题,那就真的要回到虚拟机或者物理机部署的玩法了。当然,这样的需求,我们也想过通过Operator也实现,但代价太大了,而且很不CloudNative!
将基础组件Agents从业务Pod中剥离,以上的问题都能解决了,架构上的解耦带来的好处无需多言。而且我们可以通过Kubernetes管理这些基础组件Agents了,享受其自愈、滚动升级等好处。
二、Linux共享内存机制
然而,理想很美好,现实很残酷。首先要解决的问题是,有些组件Agent与业务Pod之间是通过共享内存通信的,这跟Kubernetes&微服务的最佳实践背道而驰。
大家都知道,Kubernetes单个Pod内是共享IPC的,并且可以通过挂载Medium为Memory的EmptyDir Volume共享同一块内存Volume。
首先我们来了解一下Linux共享内存的两种机制:
其中,System V共享内存历史悠久,一般的UNIX系统上都有这套机制;而POSIX共享内存机制接口更加方便易用,一般是结合内存映射mmap使用。
mmap和System V共享内存的主要区别在于:
POSIX共享内存是基于tmpfs来实现的。实际上,更进一步,不仅PSM(POSIX shared memory),而且SSM(System V shared memory)在内核也是基于tmpfs实现的。
从这里可以看到tmpfs主要有两个作用:
虽然System V与POSIX共享内存都是通过tmpfs实现,但是受的限制却不相同。也就是说 /proc/sys/kernel/shmmax只会影响SYS V共享内存,/dev/shm只会影响Posix共享内存 。实际上,System V与Posix共享内存本来就是使用的两个不同的tmpfs实例(instance)。
SYS V共享内存能够使用的内存空间只受/proc/sys/kernel/shmmax限制;而用户通过挂载的/dev/shm,默认为物理内存的1/2。
概括一下:
POSIX共享内存与SYS V共享内存在内核都是通过tmpfs实现,但对应两个不同的tmpfs实例,相互独立。
通过/proc/sys/kernel/shmmax可以限制SYS V共享内存的最大值,通过/dev/shm可以限制POSIX共享内存的最大值(所有之和)。
三、同一Node上夸Pod的共享内存方案基础组件Agents DaemonSet部署后,Agents和业务Pod分别在同一个Node上不同的Pod,那么Kubernetes该如何支持这两种类型的共享内存机制呢?
当然,安全性上做出了牺牲,但在非容器化之前IPC的隔离也是没有的,所以这一点是可以接受的。
四、灰度上线对于集群中的存量业务,之前都是将Agents与业务打包在同一个docker image,因此需要有灰度上线方案,以保证存量业务不受影响。
$ kubectl label node $nodeName AgentsDaemonSet=YES$ kubectl taint node $nodeName AgentsDaemonSet=YES:NoSchedule
(安卓系统可左右滑动查看全部代码)
apiVersion: apps/v1kind: DaemonSetmetadata: name: demo-agent namespace: kube-system labels: k8s-app: demo-agentspec: selector: matchLabels: name: demo-agent template: metadata: annotations: scheduler.alpha.kubernetes.io/critical-pod: "" labels: name: demo-agent spec: tolerations: - key: "AgentsDaemonSet" operator: "Equal" value: "YES" effect: "NoSchedule" hostNetwork: true hostIPC: true nodeSelector: AgentsDaemonSet: "YES" containers: - name: demo-agent image: demo_agent:1.0 volumeMounts: - mountPath: /dev/shm name: shm resources: limits: cpu: 200m memory: 200Mi requests: cpu: 100m memory: 100Mi volumes: - name: shm hostPath: path: /dev/shm type: Directoryels:
k8s-app: demo-agent
spec:
selector:
matchLabels:
name: demo-agent
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
labels:
name: demo-agent
spec:
tolerations:
- key: "AgentsDaemonSet"
operator: "Equal"
value: "YES"
effect: "NoSchedule"
hostNetwork: true
hostIPC: true
nodeSelector:
AgentsDaemonSet: "YES"
containers:
- name: demo-agent
image: demo_agent:1.0
volumeMounts:
- mountPath: /dev/shm
name: shm
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
volumes:
- name: shm
hostPath:
path: /dev/shm
type: Directory总结:
在高并发业务下,尤其还是以C/C++代码实现的基础组件,经常会使用共享内存通信机制来追求高性能,本文给出了Kubernetes Pod间Posix/SystemV共享内存方式的折中方案,以牺牲一定的安全性为代价,请知悉。当然,如果微服务/容器化改造后,基础服务的Server端确定不会有压力,那么建议以SideCar Container方式将基础服务的Agents与业务Container部署在同一Pod中,利用Pod的共享IPC特性及Memory Medium EmptyDir Volume方式共享内存。
推荐阅读
关于作者:王涛,腾讯云高级工程师,西安电子科大硕士毕业,持续深耕云计算领域七年,目前在腾讯基于TKE(Tencent Kubernetes Engine)构建DevOps平台,帮助集团自研业务上云,曾在华为、唯品会、vivo从事企业私有云平台的建设工作,2014年开始专注于Kubernetes/Docker等容器技术栈在DevOps、AI Platform方向的应用,积累了大量生产经验。
关于EAWorld:微服务,DevOps,数据治理,移动架构原创技术分享。长按二维码关注!
-
2011款MAC Mini更换内存及SSD经验共享
2014-06-18 23:47:392011款MAC Mini更换内存及SSD经验共享 -
详解C++中的内存同步模式(memory order)
2020-12-26 11:35:19原子(atomic)变量的主要作用就是同步多线程间的共享内存访问,一般来讲,某个线程会创建一些数据,然后给原子变量设置标志数值(译注:此处的原子变量类似于一个flag);其他线程则读取这个原子变量,当发现其数值变为了标志... -
swap(交换内存)和shm(共享内存)的区别
2019-04-10 04:31:00在使用docker的过程中,发现docker中有很多关于内存的命令,例如: -m="10g",docker的运行内存,按照官方文档描述,应该是对应于实际机器的物理内存,因此在设置的时候,肯定是要比本机物理内存小的;单位可以是b/k...关于swap和shm的区别
在使用docker的过程中,发现docker中有很多关于内存的命令,例如:
-m="10g"
,docker的运行内存,按照官方文档描述,应该是对应于实际机器的物理内存,因此在设置的时候,肯定是要比本机物理内存小的;单位可以是b/k/m/g
-memory-swap="11g"
,内存+交换内存,即物理内存+交换内存的总大小,要大于等于上面设置的-m
的大小,设置格式同上--shm-size="10g"
,共享内存。
从表面看,共享内存和交换空间有些相似,因此关于共享内存
shm
和swap
之间的区别颇让人让人费解的问题,查了一些资料(见最后的参考)后,对于这两个内存的理解是:- swap:
是一个文件
,是使用硬盘空间的一部分作为物理内存来扩展RAM空间的- 虽然是物理硬盘的一部分,但是仍然属于RAM,并且属于易失性存储,重启机器会使数据丢失;
- 空间大小在一般情况下,swap的空间大小设置为物理内存的两倍大小;
- docker中的swap对应于物理机器linux系统中的swap
- shm:
- 在机器上挂载名可以是
dev/shm
,也可以是tmpfs
; - 是将虚拟内存的一部分挂载为临时
文件系统
,用于应用程序的加速(程序之间共享内存),原理是允许其中的数据被不同的应用程序访问; - 在
tmpfs
中创建的文件很自然地也就创建在了虚拟内存中,因此其存储性质同swap,属于易失性存储; - 在docker中使用
--shm-size
命令挂载的分区是/dev/shm
,可以在docker的命令行中使用df -h
命令查看;同时也能看到本机的物理机器上的tmpfs
分区; - 如果在运行docker的物理机器上运行
df -h
命令,内容是类似下面这样的:
看不到docker的tmpfs 7.8G 115M 7.7G 2% /dev/shm tmpfs 5.0M 4.0K 5.0M 1% /run/lock tmpfs 7.8G 0 7.8G 0% /sys/fs/cgroup
/dev/shm
空间;并且物理机器上的/dev/shm
也是挂载在tmpfs
下面的;同时物理机器上tmpfs
也挂载了其他临时分区;- 即在docker中可以看到docker的挂载情况和本地物理机器的挂载情况,而在物理机器上看不到docker中的挂载情况
- 在机器上挂载名可以是
总结
下面参考链接中给出了
swap
和shm (tmpfs)
的区别总结:- tmpfs使用内存空间而swap使用物理存储空间
- 使用
df
命令时,tmpfs可以看做是挂载的文件系统,但是看不到swap(就像使用df命令看不到物理内存一样) - swap有经验意义上推荐的大小,而tmpfs没有;tmpfs的大小与所运行系统的目的有关
- tmpfs可以使当前运行系统中的应用程序运行的更快(程序之间共享内存),而swap是缓解系统物理内存压力的
- swap空间满了表明系统正在高负荷运转,会造成性能下降甚至死机;而tmpfs满了以后并不一定有上面的情况
- tmpfs是作为“增强型”功能出现的,而swap是必须有的功能
参考
https://gerardnico.com/os/linux/shared_memory
https://kerneltalks.com/linux/difference-between-tmpfs-and-swap/
https://www.garron.me/en/bits/create-add-swap-file-ubuntu.html
https://www.experts-exchange.com/questions/27463115/Diffrence-between-swap-and-dev-shm.html -
共享内存,管道,socket等进程间通信方式的优缺点
2018-10-29 17:58:34(共享内存,管道,socket)分布式:socket是进程间通信唯一选择 进程间通信的方式有很多,常见的有信号,信号量,消息队列,管道,共享内存,和socket等,这里我们主要讨论管道,共享内存,和socket,其他的比较... -
winserver物理内存使用不到一半就频繁爆内存
2020-08-21 01:59:08使用的物理内存和内存使用的区别?提交、专用、工作集的区别?已提交又是什么东西? 如何配好winserver内存线上一直存在一个问题,内存无法最大利用化,经常出现服务崩溃问题。 winserver上有16g的物理内存,使用不... -
Linux共享内存常见问题分析
2014-02-22 22:19:15前言 这个是接上篇,本来是记录在一...System V 共享内存问题 shmget创建共享内存问题 shmget函数用来创建一个新的,或者访问一个已存在的共享内存区。 #include #include int shmget(key_t key, size_t size, int -
共享内存的系统调用
2014-06-30 21:55:30当进程不再需要共享内存时,可以使用函数shmdt释放共享内存映射,其原型如下: #include int shmdt(const void *shmaddr); 函数shmdt释放进程在地址shmaddr处映射的共享内存,参数shmaddr必须为函数... -
多进程与多线程的优劣 与 共享内存的同步问题
2016-12-03 21:28:29进程之间的地址空间是独享的,而线程是共享进程的地址空间,线程的资源比进程小,创建线程比创建进程快,线程间切换快,线程间通信快,线程资源利用率好. 下面做个补充: 1,线程挂则可能导致进程挂,稳定性差。对长... -
共享内存
2012-11-15 18:48:11简介 共享内存是一种非常重要且常用的进程间通信方式,相对于其它IPC机制,因其速度最快、效率最高,被广泛...System V IPC 为UNIX平台上的共享内存应用制定了统一的API标准,从而为在UNIX/Linux平台上进行跨 -
springboot内存占用过高问题排查 - jvm内存使用分析
2020-10-27 22:04:47排查springboot内存占用过高问题 所需命令: ps命令:Linux命令。强大的进程状态监控命令。可以查看进程以及进程中线程的当前CPU使用情况。属于当前状态的采样数据。 top命令:Linux命令。可以查看实时的CPU使用情况... -
Java虚拟机内存调优经验
2018-02-27 09:09:39转载自 http://www.cnblogs.com/jackyrong/archive/2010/01/21/1653163.html 尊重别人的劳动成果就是尊重自己...对象的堆内存由称为垃圾回收器 的自动内存管理系统回收。 堆由两部分组成: 其中eden+fromspace+t... -
Redis内存使用优化与存储
2016-04-12 14:24:26redis内部使用一个redisObject对象来表示所有的key和value。redisObject最主要的信息如下图所示: type代表一个value对象具体是何种数据类型,encoding是不同数据类型在redis内部的存储方式,比如:type=string... -
Java文件映射共享内存
2015-03-26 00:30:15通常这些是要被频繁读写的,所以用C/C++的话通常的做法是使用共享内存划分出一大块内存,然后把它又分成同样大小的小块,用其中的一块或几块来保存一个UID和其所对应的数据,并配合一些索引和分配、回收块的算法等等... -
好理解的Java内存虚假共享(False Sharing)性能损耗以及解决方案
2019-04-30 19:06:04在计算机科学中,虚假共享是一种性能降低的使用模式,它可能出现在具有由高速缓存机制管理的最小资源块大小的分布式一致高速缓存的系统中。当系统参与者将定期尝试访问,将永远不会被另一方改变数据,但这些数据共享... -
监控Java应用程序Windows内存使用情况
2019-01-20 17:08:42监控Java应用程序Windows内存使用情况 -
内存伪共享(False Sharing)
2015-04-11 10:24:29博主注:在考虑优化多线程并发的内存使用场景时, 由于CPU缓存机制不尽相同, 建议至少确保有128字节距离, 一般通过设置不使用哑元(dummy)或者跨区分配来避免命中同一缓存行, 以减少不同处理器由于缓存行相同造成的缓存... -
Linux下用信号量实现对共享内存的访问保护(一)
2012-02-07 11:17:52本文中对共享内存的实现采用了系统V的机制,我们的重点在于通过信号量来完成对不同进程间共享内存资源的一致性访问,共享内存的具体方法请参见相关资料,这里不再赘述。 首先我们先实现最简单的共享内存,一个... -
Java内存区域与内存溢出异常
2022-03-14 19:59:32Java对象结果、内存溢出 -
明解c/c++程序的内存模型--内存四区
2021-04-10 23:21:59首先说明一哈,“明解”不是要内内存四区讲的特别深入,而是给大家讲明白内存四区是个什么东西,它的基础知识,让大家在平时学习中遇见它不会特别茫然。学习内存四区还对语言的学习有特别大的帮助(本人亲身经历,... -
ipcs命令详解——共享内存、消息队列、信号量定位利器
2016-01-31 22:22:50多进程间通信常用的技术手段包括共享内存、消息队列、信号量等等,Linux系统下自带的ipcs命令是一个极好的工具,可以帮助我们查看当前系统下以上三项的使用情况,从而利于定位多进程通信中出现的通信问题。... -
JVM 内存模型
2021-05-18 22:54:00JVM 需要使用计算机的内存,Java 程序运行中所处理的对象或者算法都会使用 JVM 的内 存空间,JVM 将内存区划分为 5 块,这样的结构称之为 JVM 内存模型。 2 JVM 为什么进行内存区域划分 随着对象数量的增加,JVM ... -
UE高级性能剖析技术(三)-- Android内存分布和优化
2020-04-11 21:00:04在基于ue的手游开发中,经常会发现android系统的实际内存占用要比我们预估的高很多,优化内存的占用就要先明确究竟每1k实际的内存占用分布在哪里及如何运用工具有效的获取真实的内存组成,本文将结合项目经验详细... -
vSphere 虚拟环境中超额配置 CPU、 内存和存储的比例推荐及规划简述
2021-08-07 02:35:59现在,虚拟环境中的混合I/O模式允许不同峰值需求共享资源。管理员可能经常会超额置备资源并调整各个虚拟机的大小以满足峰值需求。CPU超配仅分配物理上可用于支持所有正在运行的工作负载的资源。被认为是最安全的方案...