KVM同步脏页原理

2023-11-09


QEMU在内存迁移阶段首先会标脏所有内存页,然后通知KVM开启脏页统计。本章主要介绍KVM在脏页统计中的作用,首先介绍intel x86脏页统计的硬件基础,然后介绍KVM中脏页统计相关数据结构、脏页开启的IOCTL命令字介绍、脏页统计发起流程,最后实验验证上述分析。

硬件基础

  • KVM脏页统计离不开硬件支持,在Intel没有引入PML(Page Modification Logging)特性之前。主要利用SPTE的D状态位跟踪脏页。在引入PML之后,则通过PML跟踪脏页,其主要功能是记录虚机写内存页的行为并将内存页的地址GPA记录下来。我们分别介绍SPTE和PML。

SPTE

硬件要素

请添加图片描述
在这里插入图片描述

  • 上图为intel Page table各个字段定义,其中bit 6称为脏页标记位,我们知道intel Page table有两个作用,一个是指向真正的物理页,一个是指向包含下级页表内容的物理页,用于线性地址转化。
  • 当一个Page table指向真正物理页的条目(作为SPTE)时,如果CPU对该SPTE指向的物理页有写操作,硬件会将脏页标记位置位,CPU下一次写该页时会再次置位(需要软件清零脏页位),通过硬件置位-软件清零的手段,软件可以跟踪到虚拟机脏页状态。

工作流程

  • TODO

PML

硬件要素

在这里插入图片描述

  • PML是Intel为支持虚拟化场景下脏页跟踪而开发的硬件特性,使用该特性涉及到Intel的几个硬件元素,下面根据以上图示一一介绍:
  1. Accessed and Dirty flags:这是EPTP字段中位于bit 6的一个标志位,当设置此标志位后,它告诉CPU每当使用EPT查询HPA时,将页结构存放的表项中的Accessed位(bit 8)置1,对于指向物理页的页表项,当往指向的物理页中写数据时,将它的Dirty位(bit 9)置1。
  2. PML flag:这是VMCS VM-Exection Controls Field区域的一个标志位,用于使能PML特性。只有在Accessed and Dirty flags位开启时,才可以使能PML。
  3. PML Buffer:一块内存区域,用来存放上一次开启PML特性之后,CPU写过的物理页的地址,大小为4K,可以存放512条GPA。KVM就是通过这个区域来跟踪内存脏页。
  4. PML Address:用来保存PML Buffer的内存物理地址,它是VMCS VM-Execution control field的一个字段。
  5. PML index:用来保存PML Buffer的索引,长度16 bit,表示范围0-511,和PML Buffer中的条目对应。PML index用来保存下一次CPU写物理页保存GPA时在PML Buffer中的位置。PML index每次递减。

工作流程

在这里插入图片描述

  • 下面介绍开启PML特性之后,记录脏页的整个工作流程,如图所示,分以下5个步骤:
  1. 当CPU想要记录内存脏页,比如迁移开始时,首先设置Accessed and Dirty flags和PML flag标志,使能脏页记录功能。当CPU写VM的物理内存页时,如果发现Accessed and Dirty和PML都使能了,会首先将对应表项的Access和Dirty位置1,然后将GPA记录到PML Buffer中。每写一次物理内存页,PML Buffer就多一条GPA的记录,PML index减1。
  2. 当PML Buffer被填满时,会产生page-modification log-full event,然后触发VMExit。
  3. CPU退出到根模式的内核态之后,KVM会判断退出原因,如果是PML Buffer满引起的退出,会将PML Buffer的内容保存下来,然后PML Buffer的索引PML index会被重新置为511。
  4. PML Buffer的内容,就是CPU最近写过的内存页地址,它就是内存的脏数据,对于内存迁移来说,该数据可以用来评估虚机的内存变化量。如果PML Buffer中内容较少,那么Qemu可以将虚机暂停然后一次性拷贝完。
  5. 当CPU不想记录内存脏页,迁移已经完成后,就可以关闭PML特性。
  • 注意:上面的过程是Intel PML特性的通用使用过程,对于kvm的实现中,并不是每次迁移开始前才开启PML特性,而是在kvm模块初始化的过程中开启,PML Buffer的分配是在vcpu创建过程中。迁移结束也不会关闭PML特性。PML特性是一直存在于KVM模块的生命周期中的。

数据结构

用户态

  • RAMList
typedef struct {
   ......
   /* 存放记录脏页的位图,一个block元素可以表示的内存范围是256K个内存页 */
    unsigned long *blocks[];
} DirtyMemoryBlocks;

typedef struct RAMList {
	......
	/* 虚机占用的所有主机上的RAM内存块集合 */
    QLIST_HEAD(, RAMBlock) blocks;
    /* 用户态从内核获取虚机脏页信息时保存到的结构体 */
    DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM];
} RAMList;
  • RAMBlock
struct RAMBlock {
	...... 
	/* 内存区域表示的最大范围,单位是字节 */
	ram_addr_t max_length;
	/* dirty bitmap used during migration */
	/* 记录该内存区域脏页情况的位图,一个内存页对应一个bit位
	    它是一个长整形指针数组,整个数组元素长度加起来转换
	    成bit数等于max_length/4K 
	    */
    unsigned long *bmap;								
	......
}
  • 用户态与脏页统计有关的数据结构有以上两个,RAMList和RAMBlock,它们各自的数据结构图示如下,既然都是统计脏页,为什么需要两个数据结构呢?个人觉得,这两个数据结构的使用场景是不一样的,RAMList用在从内核获取脏页的时候,它表示脏页的粒度是kvm中的一个slot;而RAMBlock中的位图用来描述一个RAMBlock的脏页使用情况,它表示的脏页粒度是Qemu中的一个RAMBlock。在内存迁移统计脏页过程中,会依次使用这两个数据结构统计剩余内存的脏页数量。
    在这里插入图片描述

内核态

  • vcpu_vmx
struct vcpu_vmx {
	struct page *pml_pg; 
	......
}
  • vmcs_field_to_offset_table
vmcs_field_to_offset_table[] = { 
	......
	FIELD(GUEST_PML_INDEX, guest_pml_index),
	FIELD64(PML_ADDRESS, pml_address)
	......
}
  • kvm_userspace_memory_region
/* for KVM_SET_USER_MEMORY_REGION */
struct kvm_userspace_memory_region {
	/* 内存区间所在的插槽 */
	__u32 slot;								
	/* 当flags包含KVM_SET_USER_MEMORY_REGION标识时
	   表示开启这段内存的脏页记录  
	   */
	__u32 flags;					
	/* 虚机内存区间物理地址 */		
	__u64 guest_phys_addr;
	/* 虚机内存区间大小 */
	__u64 memory_size; /* bytes */
	/* 分配给这段内存区间的实际的用户态地址HVA */
	__u64 userspace_addr; /* start of the userspace allocated memory */
};
  • kvm_dirty_log
/* for KVM_GET_DIRTY_LOG */
struct kvm_dirty_log {
	__u32 slot;
	__u32 padding1;
	union {
		void *dirty_bitmap; /* one bit per page */
		__u64 padding2;
	};
};
  • kvm_memory_slot
struct kvm_memory_slot {
	gfn_t base_gfn;
	unsigned long npages;
	unsigned long *dirty_bitmap;
	u32 flags;
    ....
};

API

  • 为了让用于态统计虚机的脏页,内核提供了两个接口,分别是KVM_SET_USER_MEMORY_REGIONKVM_GET_DIRTY_LOG,这两个接口

脏页开启

  • 内核提供了两个命令供用户态统计虚机的脏页,KVM_SET_USER_MEMORY_REGION、KVM_GET_DIRTY_LOG,KVM_SET_USER_MEMORY_REGION命令字作用在vm的fd,用来通知kvm开启对某段内存区域的脏页跟踪,结构体kvm_userspace_memory_region 是用户态传入的参数,用来描述kvm应该跟踪的内存区域,如下:
Capability: KVM_CAP_USER_MEMORY
Architectures: all
Type: vm ioctl          /* 虚机vm ioctl命令字 */
Parameters: struct kvm_userspace_memory_region (in)
Returns: 0 on success, -1 on error
 
  struct kvm_userspace_memory_region {
    __u32 slot;
    __u32 flags;
    __u64 guest_phys_addr;
    __u64 memory_size; /* bytes */
    __u64 userspace_addr; /* start of the userspace allocated memory */
  };
  /* for kvm_memory_region::flags */
  #define KVM_MEM_LOG_DIRTY_PAGES    (1UL << 0)
  #define KVM_MEM_READONLY    (1UL << 1)

脏页获取

  • KVM_GET_DIRTY_LOG命令字作用在vm的fd,用来获取内核跟踪的脏页信息,结构体kvm_dirty_log作为参数用来指定要查询的内存slot,同时保存内核的脏页查询结果,如下:
Capability: basic
Architectures: all
Type: vm ioctl
Parameters: struct kvm_dirty_log (in/out)
Returns: 0 on success, -1 on error
 
  /* for KVM_GET_DIRTY_LOG */
  struct kvm_dirty_log {
    /* 输入,指定要查询脏页的内存slot */
    __u32 slot;
    __u32 padding;
    union {
        /* 输出,保存kvm查询到的脏页 */
        void __user *dirty_bitmap; /* one bit per page */
        __u64 padding;
    };
  };

流程

使能记录

  • KVM的PML特性在模块初始化的过程中完成,每创建一个vcpu,需要为其分配PML Buffer并初始化PML Index。
使能PML特性:
/* kvm模块初始化入口  */
vmx_init										
	kvm_init
		kvm_arch_hardware_setup
			vmx_x86_ops.hardware_setup
				hardware_setup
					/* 设置VMCS区域内存的内容
					   在VMLAUNCH和VMRESUME的时候被加载到VMCS区域
					 */
					setup_vmcs_config
						/* 设置SECONDARY_EXEC_ENABLE_PML标识使能PML */
						opt2 = SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES | XXX | SECONDARY_EXEC_ENABLE_PML
						adjust_vmx_controls(min2, opt2, MSR_IA32_VMX_PROCBASED_CTLS2, &_cpu_based_2nd_exec_control)
						vmcs_conf->cpu_based_2nd_exec_ctrl = _cpu_based_2nd_exec_control;
设置PML Buffer地址和PML Index初始值:
/* vcpu创建入口 */
vmx_create_vcpu
	vmx_vcpu_setup
		/* 如果使能了PML特性,分配一个物理页给pml_pg用作PML Buffer */
		if (enable_pml) {
			vmx->pml_pg = alloc_page(GFP_KERNEL | __GFP_ZERO);
		}
		/* 将分配好的PML Buffer地址写入VMCS的对应区域,同时初始化PMLIndex为511  */
		if (enable_pml) {
			vmcs_write64(PML_ADDRESS, page_to_phys(vmx->pml_pg)); 
			vmcs_write16(GUEST_PML_INDEX, PML_ENTITY_NUM - 1);
		}

记录脏页

流程图

在这里插入图片描述

具体过程

  • 根据PML的硬件特性,每当CPU在Guest态根据EPT转换地址后,写数据到物理页,这时如果PML特性开启,在设置EPT页表项的Dirty位之后,还会将GPA地址写入PML Buffer。这里intel暗含的假设是之后Dirty标志位从0变成1,才能写PML Buffer,而Dirty标志位的变成1之后的清零动作是软件做的,因此如果想要记录一个slot的脏页,需要将引用这个slot的所有页表项的Dirty标志位都清零。开启脏页记录需要做以下两件事情:
  1. 清零Dirty位:KVM的实现中,在创建slot时,如果不想记录某个slot包含的所有物理页的是否为脏,需要默认将这些物理页对应的页表项的Dirty页置位,因为如果Dirty位是0,Guest态CPU写物理页时会将其置1并且填充GPA到PML Buffer,如果PML Buffer满了,就会触发VMExit,增加不必要的开销。反之,要记录脏页,首先需要将指向slot包含的所有物理页的spte的Dirty位清零,这里需要根据gfn找到指向该gfn对应页的spte,反向映射数组rmap就派上了用场。
  2. 物理页开启写保护:除了清零页表项的Dirty位,记录脏页还需要开启页的写保护,在脏页记录的过程中,所有slot包含的物理页变成只读,当CPU写访问这个页时,发生缺页异常,kvm会重新分配一个新的页给CPU。在脏页记录关闭后,才能将写保护去掉,slot包含的所有页变成可读写。
/* kvm ioctl入口 */
kvm_vm_ioctl
	/* slot命令字,内核根据传入的参数
	   对应地增加,删除和更新slot
	   这里要跟踪slot的脏页,算在更新里面
	   */
    case KVM_SET_USER_MEMORY_REGION
    kvm_vm_ioctl_set_memory_region
        kvm_set_memory_region
            __kvm_set_memory_region
            	/* 根据用户态传入的参数,设置slot,这里是开启脏页的记录*/
                kvm_set_memslot
                    kvm_arch_commit_memory_region           
                        kvm_mmu_slot_apply_flags
                        	/* 根据intel vmx的特性开启脏页记录 */
                        	if (new->flags & KVM_MEM_LOG_DIRTY_PAGES) {
                        		if (kvm_x86_ops.slot_enable_log_dirty) {
                        			/* 对于x86平台,如果intel提供了PML机制可以记录脏页,进入这个流程 */
									kvm_x86_ops.slot_enable_log_dirty(kvm, new)
									kvm_x86_ops.slot_enable_log_dirty   <=>   vmx_slot_enable_log_dirty
								} else {
									/* 在没有PML机制的情况下,使用页只读的方式记录脏页 
									 * 判断两种情况,分别处理:
									 * 1. 首次迭代时位图都标记为1,不需要标记4k小页,但需要标记
									 * 2M的大页为只读,这样kvm在处理虚机大页访问异常时会将其拆
									 * 分成小页。
									 * 2. 对于其它轮次的迭代,需要将所有4k页的页表项都标记为只读
									 */
                        			int level =
										kvm_dirty_log_manual_protect_and_init_set(kvm) ?
										PG_LEVEL_2M : PG_LEVEL_4K;
										kvm_mmu_slot_remove_write_access(kvm, new, level);
                            	}	
                          	}
  • 分析x86架构下使用PML机制记录脏页的流程,kernel中关于PML场景下的comment如下:
        /*
         * Dirty logging tracks sptes in 4k granularity, meaning that
         * large sptes have to be split.  If live migration succeeds,
         * the guest in the source machine will be destroyed and large
         * sptes will be created in the destination.  However, if the
         * guest continues to run in the source machine (for example if
         * live migration fails), small sptes will remain around and
         * cause bad performance.
         *
         * Scan sptes if dirty logging has been stopped, dropping those
         * which can be collapsed into a single large-page spte.  Later
         * page faults will create the large-page sptes.
         */
  • 流程如下:
vmx_slot_enable_log_dirty
	kvm_mmu_slot_apply_flags
		/* cpu_dirty_log_size存在表明开启了PML,使能脏页日志跟踪分两种情况 
         * 1: 对于4K普通的页,只需要清零D-bit状态位即可
         * 2: 对于2M大页,除了清零D-bit状态位,还需要使能写保护
         *    使得虚机访问大页页表时也能触发异常,陷入kvm后以4k页的粒度分配虚机的页
         *    从而将大页拆分为小页
         */
		if (kvm_x86_ops.cpu_dirty_log_size) {
		    /* 清零D状态位,方便硬件下一次统计 */
			kvm_mmu_slot_leaf_clear_dirty(kvm, new);
			   /* 这里通过rmap数据,遍历指向slot包含的所有物理页的spte
	 	 	    * 针对每个spte调用__rmap_clear_dirty函数 
 	 	 	    */
 			    slot_handle_leaf_4k(kvm, memslot, __rmap_clear_dirty, false)
			/* 开启所有2M大页页表项的写保护功能 */
			kvm_mmu_slot_remove_write_access(kvm, new, PG_LEVEL_2M);
		} else {
			kvm_mmu_slot_remove_write_access(kvm, new, PG_LEVEL_4K);
		}
		
/* 清零表项的Dirty位*/
__rmap_clear_dirty
	spte_clear_dirty
		/* 将kvm模块初始化时设置的Dirty默认值取出,用于设置spte的Dirty位 */
		spte &= ~shadow_dirty_mask                          			
		mmu_spte_update
			......
			__set_spte
				/* 更新spte表项 */
				WRITE_ONCE(*sptep, spte)
				
/* 设置slot包含的所有页写保护WP */
kvm_mmu_slot_remove_write_access
	slot_handle_large_level(kvm, memslot, slot_rmap_write_protect, false);
		__rmap_write_protect(kvm, rmap_head, false)
			spte_write_protect(sptep, pt_protect)
				/* 清零页表项的bit 1,不允许CPU写物理页 */
				spte = spte & ~PT_WRITABLE_MASK
				mmu_spte_update
					......
					__set_spte
					/* 更新spte表项 */
					WRITE_ONCE(*sptep, spte)
  • 脏页日志开启后,对于使用位图方式跟踪的4k页,缺页异常的快速处理逻辑中,会首先将脏页在slot的位图中标记,然后将页表项标记为可写,不会进入慢速处理分配页表的阶段,因为这些被标记为写保护的页,本身可能已经分配了物理地址,对于使用PML方式跟踪的4k页同样如此。但是对于PML方式跟踪的大页,这里仍然会开启写保护,其目的是让缺页的慢速路径去处理缺页,使其重新分配一块4K的物理页,从而实现缺页在脏页日志开启情况下大页拆小页的逻辑。代码如下:
fast_page_fault
       /*
         * Currently, to simplify the code, write-protection can
         * be removed in the fast path only if the SPTE was
         * write-protected for dirty-logging or access tracking.
         */
        if (fault->write &&
            spte_can_locklessly_be_made_writable(spte)) {
            new_spte |= PT_WRITABLE_MASK;

            /*
             * Do not fix write-permission on the large spte.  Since
             * we only dirty the first page into the dirty-bitmap in
             * fast_pf_fix_direct_spte(), other pages are missed
             * if its slot has dirty logging enabled.
             *
             * Instead, we let the slow page fault path create a
             * normal spte to fix the access.
             *
             * See the comments in kvm_arch_commit_memory_region().
             */
            if (sp->role.level > PG_LEVEL_4K)
                break;
        }

获取脏页

流程图

在这里插入图片描述

具体过程

  • 获取脏页的流程,实际上也分为了两个步骤,第一步是拷贝dirty bitmap,第二步是清零脏页的标志。
  • kvm在早期的实现中,将这两步合在一起,在KVM_GET_DIRTY_LOG ioctl中实现了,由于第二步需要拿mmu_lock锁修改页表,并且不知道哪些页需要清零,因此会清零虚机所有页,而vcpu缺页退出guest态时,kvm处理缺页这个操作需要竞争mmu_lock,长时间持有mmu_lock会影响vcpu的内存访问性能,因此第二步的开销很大。
  • kvm在之后改进了脏页获取流程,引入了KVM_CAP_MANUAL_DIRTY_LOG_PROTECT特性,将脏页获取分成了两个ioctl命令字,KVM_GET_DIRTY_LOGKVM_CLEAR_DIRTY_LOG,对应之前的两个步骤,第一个命令字只负责拷贝dirty bitmap,第二个命令只负责清零脏页,用户态获取到dirty bitmap之后,可以知道哪些页是脏的,因此KVM_CLEAR_DIRTY_LOG可以是虚机所有页集合的子集,在修改页表时效率会更高。
  • 下面分析具体代码:
kvm_vm_ioctl
    case KVM_GET_DIRTY_LOG: 
        kvm_vm_ioctl_get_dirty_log
            kvm_get_dirty_log_protect 	
                slots = __kvm_memslots(kvm, as_id);
                memslot = id_to_memslot(slots, id);
                /* x86架构使用PML机制获取脏页 */
                kvm_arch_sync_dirty_log
                    kvm_x86_ops.flush_log_dirty <=>   vmx_flush_log_dirty
                        /* kick每个vcpu让其vmexit,这样在vmexit的路径上可以更新pml buffer */
                        kvm_flush_pml_buffers
                            kvm_vcpu_kick
                /* dirty bitmap获取到之后,如果使能了KVM_CAP_MANUAL_DIRTY_LOG_PROTECT
                 * 特性,则跳过清零脏页的步骤,直接拷贝dirty bitmap */
              	if (kvm->manual_dirty_log_protect) {
              	    dirty_bitmap_buffer = dirty_bitmap;
              	} else {
              		/* 获取mmu_lock锁,修改页表,将对应位清零 */
					spin_lock(&kvm->mmu_lock);
						kvm_arch_mmu_enable_log_dirty_pt_masked(kvm, memslot,
													offset, mask);

					spin_unlock(&kvm->mmu_lock);
				}
                kvm_arch_flush_remote_tlbs_memslot
                /* 拷贝dirty bitmap到用户态 */
                copy_to_user(log->dirty_bitmap, dirty_bitmap_buffer, n)                   
  • 使用PML机制获取dirty bitmap时,只是将所有vcpu kick了一遍,具体的更新操作在vcpu从guest退出的路径上完成,简单分析下:
vmx_handle_exit
	if (enable_pml)
		vmx_flush_pml_buffer(vcpu);
			/* 遍历PML buffer的entry,将其更新到内存页所属的slot的dirty bitmap */
			for (; pml_idx < PML_ENTITY_NUM; pml_idx++) {
				gpa = pml_buf[pml_idx];
				kvm_vcpu_mark_page_dirty(vcpu, gpa >> PAGE_SHIFT);
					memslot = kvm_vcpu_gfn_to_memslot(vcpu, gfn);
					mark_page_dirty_in_slot(vcpu->kvm, memslot, gfn);
			}
  • 分析一下KVM_CAP_MANUAL_DIRTY_LOG_PROTECT特性下清零脏页的流程:
kvm_vm_ioctl
	case KVM_CLEAR_DIRTY_LOG:
		kvm_vm_ioctl_clear_dirty_log
			kvm_clear_dirty_log_protect
				/* 清零脏页前首先同步之前的脏页信息,使dirty bitmap处于最新状态 */
				kvm_arch_sync_dirty_log
				/* 将最新的脏页信息拷贝到用户态 */
				copy_from_user(dirty_bitmap_buffer, log->dirty_bitmap, n)
				/* 拿mmu_lock锁,准备清零脏页,也就是使能脏页日志 */
				spin_lock(&kvm->mmu_lock)
					kvm_arch_mmu_enable_log_dirty_pt_masked
				spin_unlock(&kvm->mmu_lock)

实验

  • 下面两个commit是基于dirty-bitmap机制脏页同步计算脏页速率的commit:
    https://github.com/qemu/qemu/commit/4998a37e4bf2bc47f76775e6e6a0cd50bacfb16a
    https://github.com/qemu/qemu/commit/826b8bc80cb191557a4ce7cf0e155b436d2d1afa
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

KVM同步脏页原理 的相关文章

  • vSphere Client(Vcenter)上传ISO镜像

    不少新手在ESXi上安装好虚拟机后 都要寻找浏览器的ios镜像 但同学们会在这里卡顿 找不到上传ios的路径 今天就来讲一讲 上传的问题 一 方法一 我初学时 一样在这里卡顿 找不到上传的路径 在网上搜索 确实找到了一种上传的方法 在这里转
  • VMware Workstation无法提供该虚拟机所需的所有图形功能

    报错信息 VMware Workstation无法提供该虚拟机所需的所有图形功能 在该虚拟机引导后 图形硬件 图形驱动程序或Vware软件版本可能已发生变化 该虚拟机将继续运行 但在关闭该虚拟机之前 某些图形操作可能会出现不可预见的行为 原
  • 59 KVM Skylark虚拟机混部-概述、架构及特性

    文章目录 59 KVM Skylark虚拟机混部 概述 架构及特性 59 1 Skylark概述 59 1 1 问题背景 59 1 2 总体介绍 59 2 架构及特性 59 2 1 总体实现框架 59 2 2 功耗干扰控制 59 2 3 L
  • 全/半虚拟化、硬件/软件辅助的全虚拟化之间的区别与联系

    全虚拟化 不需要对GuestOS操作系统软件的源代码做任何的修改 就可以运行在这样的VMM中 在全虚拟化的虚拟平台中 GuestOS并不知道自己是一台虚拟机 它会认为自己就是运行在计算机物理硬件设备上的HostOS 因为全虚拟化的VMM会将
  • 详解KVM虚拟化原理

    详解KVM虚拟化原理 KVM架构 KVM Kernel based Virtual Machine 包含一个为处理器提供底层虚拟化 可加载的核心 模块kvm ko kvm intel ko或kvm amd ko 使用QEMU QEMU KV
  • KVM MMU EPT内存管理

    转载请注明 转载自博客xelatex KVM 并附本文链接 谢谢 注 文章中采用的版本 Linux 3 11 https www kernel org pub linux kernel v3 x linux 3 11 tar gz qemu
  • nvidia-docker容器迁移导致GPU启动失败解决方案

    引言 起因是最近发现一个很有趣的问题 当我的docker容器迁移到另一台服务器去 因为GPU版本不一致导致项目启动是会报错为 CUDA error CUDA ERROR NO DEVICE no CUDA capable device is
  • 57 KVM工具使用指南-制作 LibcarePlus 热补丁

    文章目录 57 KVM工具使用指南 制作 LibcarePlus 热补丁 57 1 概述 57 2 手动制作 57 3 通过脚本制作 57 KVM工具使用指南 制作 LibcarePlus 热补丁 57 1 概述 LibcarePlus 支
  • 解决qemu虚拟机图形界面卡死问题

    1 基础环境 Virtio gpu双heads 4 9 0内核 xserver1 9 3 modesettings0 5 0驱动 2 问题描述 终端中打开大量文字内容 不停上下滑动 或cat大量内容的文件 操作过程中用户界面卡死 如下 3
  • VMware虚拟化- 虚拟化与VMware的基础介绍

    1 什么是虚拟化 1 1 虚拟化概念 通俗的理解 如果你问 什么是虚拟化 我想大部分人的回答都会是 就是在一个操作系统中运行另一个操作系统 虽然这个答案也没错 但这并不是真正 虚拟化 的意义 只能说是虚拟化在硬件和操作系统之间的一个实践 事
  • [转]漫谈虚拟化-计算虚拟化中的 I/O 虚拟化

    如果你认为本系列文章对你有所帮助 请大家有钱的捧个钱场 点击此处赞助 赞助额0 1元起步 多少随意 声明 本文只用于个人学习交流 若不慎造成侵权 请及时联系我 立即予以改正 锋影 email 174176320 qq com 今天 咱们继续
  • Citrix_XenDesktop7.5安装图解,实现Citrix虚拟云桌面

    Cirtrix XenDesktop 7 5 安装图解 一 安装 XenDesktop 7 5 安装 Winodws 2012 并加入域 xenad local 计算机名为 xd xenad local 过程略 安装 XenDesktop
  • kvm之多网卡队列开启设置

    背景 目前基于dpdk数据平面开发套件的应用越来越多 而dpdk对于上层应用运行时 服务的进程数多于1时 要求网卡支持多队列 否则项nginx这种多进程应用程序只能再默认配置下运行 只能启动一个worker 要求 在kvm虚机中将网卡设置支
  • KVM源代码分析1:基本工作原理

    http www oenhan com kvm src 1 13年的时候准备挖 KVM源代码分析 的坑 陆陆续续2年过去了 坑也没有填上 当时是因为对KVM了解的肤浅 真正的理解必然要深入到代码级别 所谓 摈弃皮毛 看到血肉 看到真相 当时
  • Qemu-KVM基本工作原理分析

    1 理解KVM与Qemu的关系 我们都知道开源虚拟机KVM 并且知道它总是跟Qemu结合出现 那这两者之间有什么关系呢 首先 Qemu本身并不是KVM的一部分 而是一整套完整的虚拟化解决方案 它是纯软件实现的 包括处理器虚拟化 内存虚拟化以
  • ESXI 7.0 版本配置N卡显卡直通

    ESXI 7 版本配置N卡显卡直通 前因 ESXI版本太新 网上啥参考资料没有 显卡直通各种问题 虚机一装显卡驱动就直接把宿主机直接整挂了 于是各种查资料 各种尝试 终于搞定直通问题 配置 名称 版本 服务器 DELL R720 ESXI
  • 服务器虚拟化的优势

    1 提高硬件资源使用效率 一个服务器上可以开多个虚拟机 给不同应用使用 打破一个应用一台服务器的限制 因为某具体用户使用的时间 资源有限 多个用户 应用 就可以大大提高服务器的使用效率 减少服务器数量 可以 降低购买服务器的投资 降低服务器
  • Android 模拟器在 Ubuntu 18.04 上因 SIGSEGV 崩溃

    Android Studio版本 Android Studio 3 1 2 内部版本 AI 173 4720617 建于 2018 年 4 月 14 日 它是从 Ubuntu 的 snap 商店安装的 我使用安装了kvm1 在 Ubuntu
  • 是否可以在 Azure 上运行 KVM

    Azure Fabric 似乎运行在 Hyper V 的定制版本上 是否可以在 Azure 上运行 KVM 虚拟化实例 使用嵌套虚拟化 我有一个基于 Debian 的自定义 VHD 比如说 根据本文档https learn microsof
  • 如何获取文件夹的大小,包括稀疏文件的表观大小? (du太慢了)

    我有一个包含很多KVM qcow2文件的文件夹 它们都是稀疏文件 现在我需要获取文件夹的总大小 qcow2 文件大小应计为表观大小 而不是实际大小 例如 图片 c9f38caf104b4d338cc1bbdd640dca89 qcow2 文

随机推荐

  • breach靶场练习详细全过程

    补充 桥接 nat host only三种网络模式的区别 模式 特点 场景 bridge桥接模式 特点 虚拟机使用物理机的网卡 不用虚拟网卡 占用一个ip 需要配置ip以后才可以访问互联网 场景 虚拟机需要连接实体设备的时候 nat网络地址
  • 最好用的 6 个 React Tree select 树形组件测评与推荐

    本文完整版 最好用的 6 个 React Tree select 树形组件测评与推荐 React Tree select 树形组件 1 React Sortable Tree 全功能 树状单选多选 可拖拽 过滤搜索 多种主题可选 2 Rea
  • android开发浏览器!写给1-3年安卓程序员的几点建议,聪明人已经收藏了!

    前言 作为一个程序员 如果你在新知识 新技术面前仍一无所知 依然吃着十多年前的老本 那你在知识技术上肯定落伍 如果又未能进入管理层面 那你肯定就会被长江的后浪拍在沙滩上了 而不少与时俱进 善于学习的程序员他们仍是行业的中坚力量 这只是说明当
  • 面试利器(二)-------插入排序(直接插入排序和希尔排序(Shell排序))

    一 直接插入排序 抓住关键字 插入 1 基本思想 顺序地把待排序的序列中的各个数据按其关键字的大小 插入到已排序的序列的适当位置 2 运行过程 1 将待排序序列的第一个数据看做一个有序序列 把第二个数据到最后一个数据当成是未排序序列 2 从
  • openblas第一弹:openblas 使用说明和常用接口介绍

    openblas 使用说明 openblas 是一个开源的矩阵计算库 包含了诸多的精度和形式的矩阵计算算法 就精度而言 包括float和double 两种数据类型的数据 其矩阵调用函数也是不一样 不同矩阵 其计算方式也是有所不同 姑且认为向
  • C++设计模式 - 组合模式(Composite)

    数据结构模式 常常有一 些组件在内部具有特定的数据结构 如果让客户程序依赖这些特定的数据结构 将极大地破坏组件的复用 这时候 将这些特定数据结构封装在内部 在外部提供统一的接口 来实现与特定数据结构无关的访问 是一种行之有效的解决方案 典型
  • 遗传算法基本介绍

    1 主要解决什么问题 是一种仿生全局优化算法 2 原理 思路是什么 选择 优胜劣汰 交叉 变异 一些重要概念 生物遗传概念在遗传算法中的对应关系 编码策略 常用的遗传算法编码方法主要有 二进制编码 浮点数编码等 可以证明 二进制编码比浮点数
  • 在html中加入网址,网页超链接怎么做,添加超链接网址的的详细步骤

    此系列教程主要讲解HTML从基础到精通 自己能够设计一个完整的前端网页项目 程序员写代码 在HTML中添加图片其实很简单 就是添加一个img的标签 图片标签的语法 一般有src alt width height四种属性就够用了 效果 图片的
  • 智能音箱借ChatGPT重获“新生”?

    曾经靠语音助手红极一时的智能音箱 近年来的市场表现却欠佳 据洛图科技发布的最新 中国智能音箱零售市场月度追踪 报告显示 2022年中国智能音箱总销量为2631万台 同比下降28 市场销售额为75 3亿元 同比下降25 而IDC发布的2023
  • 华为OD机试 - 太阳能板最大面积(Java)

    题目描述 给航天器一侧加装长方形或正方形的太阳能板 图中的红色斜线区域 需要先安装两个支柱 图中的黑色竖条 再在支柱的中间部分固定太阳能板 但航天器不同位置的支柱长度不同 太阳能板的安装面积受限于最短一侧的那根支柱长度 如图 现提供一组整形
  • 计算机中的打印机,如何添加打印机,教您电脑如何添加打印机

    打印机是我们工作中不可缺少的办公设备 那如果电脑上没安装打印机 可以进行打印吗 我们可以通过连接到同一网络上的打印机进行打印作业 那电脑怎样进行添加打印机呢 下面 小编给大家带来了电脑添加打印机的图文 打印机是现在我们办公设备的必要用品之一
  • 如何定位Release 版本中程序崩溃的位置 ---利用map文件 拦截windows崩溃函数

    1 案例描述 作为Windows程序员 平时最担心见到的事情可能就是程序发生了崩溃 异常 这时Windows会提示该程序执行了非法操作 即将关闭 请与您的供应商联系 呵呵 这句微软的 名言 恐怕是程序员最怕见也最常见的东西了 在一个大型软件
  • spring boot集成mybatis无法扫描mapper文件(坑)

    大半天耗在这上面 真的无语了 现象解决了 原因待查找 首先 如果你的spring boot集成mybatis项目报这个错 同时你使用的是YML的配置方式 再同时你用的是Intellij 那么就往下看吧 解决方法就是 使用这种配置方式 命名为
  • 马虎的算式

    标题 马虎的算式 小明是个急性子 上小学的时候经常把老师写在黑板上的题目抄错了 有一次 老师出的题目是 36 x 495 他却给抄成了 396 x 45 但结果却很戏剧性 他的答案竟然是对的 因为 36 495 396 45 17820 类
  • 刷题之反转字符串

    编写一个函数 其作用是将输入的字符串反转过来 输入字符串以字符数组 s 的形式给出 不要给另外的数组分配额外的空间 你必须原地修改输入数组 使用 O 1 的额外空间解决这一问题 示例 1 输入 s h e l l o 输出 o l l e
  • LAST_INSERT_ID使用造成订单串单问题

    订单串单问题 代码 String sql insert into this update sql List
  • 用动态数组实现了顺序表

    用动态数组实现了顺序表 作者 吕翔宇 e mail 630056108 qq com ALL RIGHTS RESERVED 版权所有 include
  • Spring Boot定时任务在分布式环境下的轻量级解决方案

    文章非原创 转载简书 原作者 foundwei 转载链接 https www jianshu com p 41970ba48453 Spring Boot提供了一个叫做Spring Task的任务调度工具 支持注解和配置文件形式 支持Cro
  • CGAL计算几何算法库安装和使用(一)

    CGAL是使用C 开发的计算几何算法库 提供Delaunay三角网 网格生成 多边形 以及各种几何处理算法 应用领域 计算机图形学 科学可视化 计算机辅助设计与建模 地理信息系统 分子生物学 医学影像学 机器人学和运动规划 和数值方法 1
  • KVM同步脏页原理

    文章目录 硬件基础 SPTE 硬件要素 工作流程 PML 硬件要素 工作流程 数据结构 用户态 内核态 API 脏页开启 脏页获取 流程 使能记录 记录脏页 流程图 具体过程 获取脏页 流程图 具体过程 实验 QEMU在内存迁移阶段首先会标